并发编程典型框架
服务器阻塞于accept函数调用,当客户端申请连接请求时客户端与服务器的状态
从accept函数返回后,新的连接被内核接受,创建新的connfd套接字
通过fork父进程可以创建子进程,让其代替自己完成读写数据操作
此时listenfd与connfd被父子进程所共享,接下来父进程关闭连接套接字只负责监听,但父进程可再次调用accept函数准备处理下一个客户端连接请求,而子进程关闭监听套接字只负责读写数据
服务器代码
#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h> #include<string.h> int main(int argc,char * argv[]) { pid_t pid; int listenfd,connfd=0; char sendbuf[100]= {"success"},revbuf[100]= {}; struct sockaddr_in ser,clt; socklen_t len=sizeof(clt); listenfd=socket(AF_INET,SOCK_STREAM,0); ser.sin_family = AF_INET; ser.sin_port = htons(8001); ser.sin_addr.s_addr = inet_addr("127.0.0.1"); int optval=1; if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))< 0) { printf("setsockopt bind error!\n"); exit(0); } if(bind(listenfd,(struct sockaddr*)&ser,sizeof(ser))<0) { printf("bind failed!\n"); exit(0); } if(listen(listenfd,SOMAXCONN)<0) { printf("listen failed!\n"); exit(0); } while(1) { connfd=accept(listenfd,(struct sockaddr*)&clt,(socklen_t *)&len); if(connfd==-1) { printf("connect failed!\n"); } pid=fork(); if(pid==0) { close(listenfd); printf("child process running\n"); while(1) { int ret=read(connfd,revbuf,sizeof(revbuf)); if(ret<0) { printf("read failed!\n"); exit(0); } else if(ret==0) { printf("client closed\n"); exit(0); } printf("server revmsg:%s\n",revbuf); write(connfd,sendbuf,sizeof(sendbuf)); memset(revbuf,0,sizeof(revbuf)); } } else if(pid>0) { close(connfd); } else { printf("create failed!\n"); close(connfd); close(listenfd); exit(0); } } if(pid==0) { close(connfd); } else { close(listenfd); } return 0; }
客户端代码
#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h> #include<string.h> int main(int argc,char *argv[]) { struct sockaddr_in user; int sockfd; char sendbuf[100],revbuf[100]; sockfd=socket(AF_INET,SOCK_STREAM,0); if(sockfd==-1) { printf("socket failed!\n"); exit(0); } user.sin_family = AF_INET; user.sin_port = htons(8001); user.sin_addr.s_addr = inet_addr("127.0.0.1"); if ( connect(sockfd, (struct sockaddr*) (&user), sizeof(user)) < 0) { perror("connect failed!\n"); exit(0); } while(~scanf("%s",sendbuf)) { write(sockfd,sendbuf,sizeof(sendbuf)); read(sockfd,revbuf,sizeof(revbuf)); printf("client revmsg:%s\n",revbuf); memset(sendbuf,0,sizeof(sendbuf)); memset(sendbuf,0,sizeof(revbuf)); } close(sockfd); return 0; }