linux——回射服务器多并发(多进程)
多并發(fā)原理如圖,多個(gè)客戶(hù)端連接一個(gè)服務(wù)器,無(wú)論哪個(gè)客戶(hù)端發(fā)送數(shù)據(jù)給服務(wù)器,服務(wù)器都能把數(shù)據(jù)準(zhǔn)確的返回給這個(gè)客戶(hù)端。
在socket編程中,socket這種文件描述符被默認(rèn)設(shè)置為阻塞,故而read函數(shù)和accept函數(shù)時(shí)阻塞函數(shù),read函數(shù)只有從緩沖區(qū)讀到數(shù)據(jù)了才返回,否則一直等待,程序一直卡在這個(gè)位置;accept函數(shù)只要有客戶(hù)端連接到服務(wù)器就返回,否則一直等待,程序一直卡在這個(gè)位置。就很容易出現(xiàn)能發(fā)數(shù)據(jù)但連不上其他客戶(hù)端或者只能連不能發(fā)數(shù)據(jù)的問(wèn)題,為避免這種情況的發(fā)生,就需要程序同時(shí)檢測(cè)有沒(méi)有客戶(hù)端連接和讀取緩沖區(qū)數(shù)據(jù),這里我們就以多進(jìn)程的方式來(lái)實(shí)現(xiàn)多并發(fā)。父進(jìn)程用于連接客戶(hù)端,只要有客戶(hù)端連接就創(chuàng)建一個(gè)進(jìn)程,用于與服務(wù)器通信。
服務(wù)器
#include <sys/socket.h> #include <unistd.h> #include <arpa/inet.h> #include <stdio.h> #include <string.h> #include <netinet/in.h> #include <sys/types.h>void do_work(int client_sock,char *ip_addr) {char arr[100]={0};while(1){memset(arr,0,sizeof(arr));int ret=read(client_sock,arr,sizeof(arr));//當(dāng)客戶(hù)端關(guān)閉,read函數(shù)立即返回0if(ret==0){printf("%s 客戶(hù)機(jī)已關(guān)閉\n",ip_addr);break;}printf("%s :",ip_addr);fputs(arr,stdout);write(client_sock,arr,ret);} }int inter() {int client_sock=0;struct sockaddr_in sock;memset(&sock,0,sizeof(sock));sock.sin_family=AF_INET;sock.sin_port=htons(5188);sock.sin_addr.s_addr=htonl(INADDR_ANY);int sockid=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);const int on=1;if(setsockopt(sockid,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on))<0)//設(shè)置端口可重復(fù)利用{printf("setsockopt\n");return 0;}if(bind(sockid,(struct sockaddr *)&sock,sizeof(sock))<0){printf("bind\n");return 0;}if(listen(sockid,SOMAXCONN)<0){printf("listen\n");return 0;}struct sockaddr_in other_sock;socklen_t other_socklen=sizeof(other_sock);pid_t pid=0,son_pid=0;while(1){client_sock=accept(sockid,(struct sockaddr *)&other_sock,&other_socklen);//父進(jìn)程處理與客戶(hù)端的連接if(client_sock<0){printf("accept\n");return 0;}char *ip_addr=inet_ntoa(other_sock.sin_addr);printf("ip=%s 已連接\n",ip_addr);pid=fork();//只要有客戶(hù)端與服務(wù)器連接就創(chuàng)建一個(gè)進(jìn)程if(pid==0)//子進(jìn)程{close(sockid);//子進(jìn)程不用sockid需要將其關(guān)閉do_work(client_sock,ip_addr);//子進(jìn)程用于處理與客戶(hù)端的收發(fā)數(shù)據(jù)操作break;}else//父進(jìn)程{close(client_sock);//父進(jìn)程不用client_sock需要將其關(guān)閉}}close(sockid);return 0; }int main() {inter();return 0; }客戶(hù)端
#include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h>int main() {struct sockaddr_in sock;memset(&sock,0,sizeof(sock));sock.sin_family=AF_INET;sock.sin_port=htons(5188);sock.sin_addr.s_addr=inet_addr("127.0.0.1");int sockid=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);socklen_t socklen=sizeof(sock);if(connect(sockid,(struct sockaddr *)&sock,socklen)<0){printf("connect\n");return 0;}char send[100]={0};char arr[100]={0};while(1) {fgets(send,sizeof(send),stdin);//從標(biāo)準(zhǔn)輸入獲取數(shù)據(jù)write(sockid,send,strlen(send));if(strcmp(send,"NULL\n")==0)//輸入NULL退出客戶(hù)端{break;}read(sockid,arr,sizeof(arr));fputs(arr,stdout);memset(arr,0,strlen(arr));memset(send,0,strlen(send));}close(sockid);return 0; }多線(xiàn)程方式請(qǐng)點(diǎn)此處
總結(jié)
以上是生活随笔為你收集整理的linux——回射服务器多并发(多进程)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Python获取硬件信息(硬盘序列号,C
- 下一篇: 一些书评网站