Linux网络编程怎么使用多进程实现服务器并发访问.docx
《Linux网络编程怎么使用多进程实现服务器并发访问.docx》由会员分享,可在线阅读,更多相关《Linux网络编程怎么使用多进程实现服务器并发访问.docx(3页珍藏版)》请在冰豆网上搜索。
Linux网络编程怎么使用多进程实现服务器并发访问
Linux网络编程怎么使用多进程实现服务器并发访问
今天就有读者问小编我了,Linux网络编程怎么使用多进程实现服务器并发访问?
然后小编我通过查阅相关资料后,就把相关的解决方法分享到这里吧,以下就是具体内容:
采用多进程的方式实现服务器的并发访问的经典范例。
程序实现功能:
1.客户端从标准输入读入一行文字,发送到服务器. 2.服务器接收到客户端发来的文字后,原样返回给客户端. 3.客户端接收到服务器的发来的文字后,输出到标准输出,然后继续以上步骤。
服务器端过程:
建立好监听套接字后,等待客户端的连接,接收到一个连接后,创建一个子进程来与客户端进行通信,主进程则继续等待其他客户端的连接。
代码如下:
#include #include #include #include #include #include #include #include #include #defineSERV_PORT1113 #defineLISTENQ32 #defineMAXLINE1024 /***连接处理函数***/ voidstr_echo(intfd); int main(intargc,char*argv[]){ intlistenfd,connfd; pid_tchildpid; socklen_tclilen; structsockaddr_inservaddr; structsockaddr_incliaddr; if((listenfd=socket(AF_INET,SOCK_STREAM,0))==-1){ fprintf(stderr,"Socketerror:
%s\n\a",strerror(errno)); exit
(1); } /*服务器端填充sockaddr结构*/ bzero(&servaddr,sizeof(servaddr)); servaddr.sin_family=AF_INET; servaddr.sin_addr.s_addr=htonl(INADDR_ANY); servaddr.sin_port=htons(SERV_PORT); /*捆绑listenfd描述符*/ if(bind(listenfd,(structsockaddr*)(&servaddr),sizeof(structsockaddr))==-1){ fprintf(stderr,"Binderror:
%s\n\a",strerror(errno)); exit
(1); } /*监听listenfd描述符*/ if(listen(listenfd,5)==-1){ fprintf(stderr,"Listenerror:
%s\n\a",strerror(errno)); exit
(1); } for(;;){ clilen=sizeof(cliaddr); /*服务器阻塞,直到客户程序建立连接*/ if((connfd=accept(listenfd,(structsockaddr*)(&cliaddr),&clilen))==-1){ fprintf(stderr,"Accepterror:
%s\n\a",strerror(errno)); exit
(1); } //有客户端建立了连接后 if((childpid=fork())==0){/*子进程*/ close(listenfd);/*关闭监听套接字*/ str_echo(connfd);/*处理该客户端的请求*/ exit(0); } close(connfd);/*父进程关闭连接套接字,继续等待其他连接的到来*/ } } voidstr_echo(intsockfd){ ssize_tn; charbuf[MAXLINE]; again:
while((n=read(sockfd,buf,MAXLINE))>0) write(sockfd,buf,n); if(n<0&&errno==EINTR)//被中断,重入 gotoagain; elseif(n<0){//出错 fprintf(stderr,"readerror:
%s\n\a",strerror(errno)); exit
(1); } } 客户端过程:
创建连接套接字,主动向服务器发起连接请求,建立连接后,等待标准输入,输入完成后,将输入的内容发送给服务器,接着接收服务器发送过来的内容,并将接收到的内容输出到标准输出。
代码如下:
#include #include #include #include #include #include #include #include #include #defineSERV_PORT1113 #defineMAXLINE1024 voidstr_cli(FILE*fp,intsockfd); int main(intargc,char**argv) { intsockfd; structsockaddr_inservaddr; if(argc!
=2){ fprintf(stderr,"usage:
tcpcli\n\a"); exit(0); } if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1){ fprintf(stderr,"Socketerror:
%s\n\a",strerror(errno)); exit
(1); } /*客户程序填充服务端的资料*/ bzero(&servaddr,sizeof(servaddr)); servaddr.sin_family=AF_INET; servaddr.sin_port=htons(SERV_PORT); if(inet_pton(AF_INET,argv[1],&servaddr.sin_addr)<=0){ fprintf(stderr,"inet_ptonError:
%s\a\n",strerror(errno)); exit
(1); } /*客户程序发起连接请求*/ if(connect(sockfd,(structsockaddr*)(&servaddr),sizeof(structsockaddr))==-1){ fprintf(stderr,"connectError:
%s\a\n",strerror(errno)); exit
(1); } str_cli(stdin,sockfd);/*doitall*/ exit(0); } void str_cli(FILE*fp,intsockfd) { intnbytes=0; charsendline[MAXLINE],recvline[MAXLINE]; while(fgets(sendline,MAXLINE,fp)!
=NULL){//从标准输入中读取一行 write(sockfd,sendline,strlen(sendline));//将该行发送给服务器 if((nbytes=read(sockfd,recvline,MAXLINE))==0){//从sockfd读取从服务器发来的数据 fprintf(stderr,"str_cli:
serverterminatedprematurely\n"); exit
(1); } recvline[nbytes]='\0'; fputs(recvline,stdout); } } 运行结果:
1.首先启动服务器端程序。
viidiot@ubuntu$./dissrv&(在后台运行) 2.启动一个客户端 viidiot@ubuntu$./discli127.0.0.1 hello,world!
(客户端输入的内容) hello,world!
(服务器端返回的内容) 3.输入命令netstat-at查看tcp的连接情况,可以发现服务器端与客户端已经建立起了一个连接,而服务器的主进程则仍然在1113端口监听,等待连接其他连接的到来。
viidiot@ubuntu$netstat–at tcp00*:
1113*:
*LISTEN tcp00localhost.localdom:
1113localhost.localdo:
57430ESTABLISHED tcp00localhost.localdo:
57430localhost.localdom:
1113ESTABLISHED 客户端输入EOF结束通信。
但是当我们开启多个客户端连接到服务器进行通信,完了之后通过按EOF结束通信后,可以从后台发现一个有趣的事情,即出现了大量的僵尸进程。
如下所示:
viidiot@ubuntu$ps-a PIDTTYTIMECMD 19403pts/100:
00:
00dissrv 19405pts/100:
00:
00dissrv 19423pts/100:
00:
00dissrv 19434pts/100:
00:
00dissrv 19441pts/100:
00:
00dissrv 造成大量僵尸进程的原因是,服务器子进程终止时,会发送一个SIGCHLD信号给父进程。
但我们的代码中,并没有捕获该信号,而这个信号的默认动作是忽略,因此,为了避免僵尸进程的产生,我们需要捕获SIGCHLD来清楚僵尸进程。
都清楚了么~如果觉得本文不错的话,就给小编我点个赞吧,就在文章下方哦!
!
!