网络编程:多线程编程模型
/************************************************************************* > File Name: src/echo_tcp_server_th.c > Author: sicaolong > Mail: sicaolong@163.com > Created Time: 2018年07月18日 星期三 20时22分42秒 ************************************************************************/ #include<iostream> #include<stdio.h> #include<netdb.h> #include<unistd.h> #include<stdlib.h> #include<memory.h> #include<signal.h> #include<time.h> #include <arpa/inet.h> #include"msg.h" #include <sys/types.h> #include <sys/wait.h> #include<error.h> #include<errno.h> #include<pthread.h> int sockfd; void sig_handler(int signo) { if(signo==SIGINT) { printf("server close "); //也属于步骤6 关闭socket; close(sockfd); exit(1); } } // void do_service(int fd) { //和客户端进行读写操作 ---双向通信 char buff[512]; while(1) { memset(buff,0,sizeof(buff)); printf("start read and write.... "); size_t size; if((size=read_msg(fd,buff,sizeof(buff)))<0) { perror("protocal error"); break; } else if(size==0) break; else { printf("%s ",buff); if(write_msg(fd,buff,sizeof(buff))<0) { if(errno==EPIPE) break; perror("protocal error"); } } } } //输出客户端的相关信息; void out_fd(void *arg) { int fd=(int)arg; struct sockaddr_in addr; socklen_t len=sizeof(addr); //从fd中获得连接到客户端的相关信息; if(getpeername(fd,(struct sockaddr *)&addr,&len)<0) { perror("getpeername error"); return ; } char ip[16]; memset(ip,0,sizeof(ip)); int port=ntohs(addr.sin_port); inet_ntop(AF_INET,&addr.sin_addr.s_addr,ip,sizeof(ip)); printf("%16s(%5d)closed ! ",ip,port); } //线程运行的函数; void *th_fn(void *arg) { int fd=(int)arg;//强制转换 do_service(fd);//完成服务端与客户端进行通讯; out_fd(fd);//输出客户端的相关信息; close(fd); return (void *)0; } int main(int argc, char *argv[] ) { if(argc<2) { printf("usage: %s #port ",argv[0]); exit(1); } if(signal(SIGINT,sig_handler)==SIG_ERR) { perror("signal sigint error"); exit(1); } //步骤一:创建socket //创建在内核中;是一个结构体; //AF_INET:ipv4 //sock_stream :tcp 协议; sockfd=socket(AF_INET,SOCK_STREAM,0); if(sockfd<0) { perror("socket error"); exit(1); } //步骤二:将socket和地址绑定;包括(ip。port等) struct sockaddr_in serveraddr; memset(&serveraddr,0,sizeof(serveraddr) ); //往地址中填入ip port internet地址足类型等 serveraddr.sin_family=AF_INET;//ipv4; serveraddr.sin_port=htons(atoi(argv[1]));//port serveraddr.sin_addr.s_addr=INADDR_ANY;//"192.168.0.1";//监听所有的网卡上面的客户端的链接请求; if(bind(sockfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr))<0) { perror("bind error"); exit(1); } //步骤三 //调用listen 函数启动监听 制定port监听; //通知系统去接受来自客户端的链接请求; //及其昂接受到的客户端请求放置到对应的队列中 //第二个参数: 指定队列的长度; if(listen(sockfd,10)<0) { perror("listen error"); exit(1); } //步骤四: //调用 accept函数从队列之中获得一个客户端的请求链接 //并且返回一个新的socket 描述符;针对客户端的; //如果没有客户端链接,调用这个函数会阻塞,直到获得一个客户端的链接; struct sockaddr_in clientaddr; socklen_t clientaddr_len=sizeof(clientaddr); //设置线程的分离属性; pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); while(1) { int fd=accept(sockfd,(struct sockaddr*)&clientaddr,&clientaddr_len); if(fd<0) { perror("accept error"); exit(1); } //步骤五:启动子线程程去调用I/O函数(write/read) //和链接的客户端进行双向的通信; pthread_t th; int err; if((err=pthread_create(&th,&attr,th_fn,(void *)fd))!=0) perror("pthread create error"); pthread_attr_destroy(&attr); } return 0; }
上一篇:
通过多线程提高代码的执行效率例子
下一篇:
matlab线性规划--简单入门