一、应用场景
- 最简单的socket示列代码只能一个客户端连接一个服务器,并不支持多个客户端对服务器的连接,为了能让多个客户端进行连接所以需要多进程或者多线程处理
二、思路解析
服务器端的程序是俩个套接字socket创建一个lfd,accept创建一个cfd阻塞连接套接字
所以只需要在fork创建的子线程里面处理与客户端的数据通信,在父进程处理连接客户端的数量处理,也就是回收进程资源。
Socket(); //创建监听套接字lfd
Bind(); //绑定服务器地址结构
Listen(); //设置监听上限
while(1){cfd=Accept();pid=fork();if(pid==0){close(lfd); //子进程用不到lfdread(cfd);数据处理;write(cfd);}else if(pid>0){close(cfd); //父进程用不到cfd}
}
总结:
子进程:c
- close(lfd);
- read();
- 数据处理;
- wirte();
父进程:
- 注册信号捕捉函数:SIGNAL;
- 在回调函数中完成子进程回收:while(waitpid());
三、示列demo
重要API
-
socket套接字
socket、bind、listen、accept、connect -
文件API
open、read、write、close -
进程API
sigaction waitpid waitppid
多进程并发服务器未带回收进程处理
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <stdio.h>
#include <error.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/wait.h>
#include <ctype.h>
#include <signal.h>#define SERIVER_PORT 9999int main(void)
{pid_t pid;int lfd, cfd;int ret, i;struct sockaddr_in myseriver;struct sockaddr_in myclient;int myclient_len = 0;char buf[100] = {0};lfd = socket(AF_INET, SOCK_STREAM, 0);if (lfd < 0){perror("socket is error");exit(1);}myseriver.sin_family = AF_INET;myseriver.sin_port = htons(SERIVER_PORT);myseriver.sin_addr.s_addr = htonl(INADDR_ANY);ret = bind(lfd, (struct sockaddr *)&myseriver, sizeof(myseriver));if (ret < 0){perror("bind is error");exit(1);}ret = listen(lfd, 128);if (ret < 0){perror("listen is error");exit(1);}myclient_len = sizeof(myclient);while (1){cfd = accept(lfd, (struct sockaddr *)&myclient, &myclient_len);if (cfd < 0){perror("accept is error");exit(1);}pid = fork();if (pid == 0){close(lfd);printf("childinit is success");while (1){ret = read(cfd, buf, sizeof(buf));if (ret == 0){close(cfd);exit(1);}for (i = 0; i < ret; i++)buf[i] = toupper(buf[i]);write(cfd, buf, ret);write(STDOUT_FILENO, buf, ret);}}else if (pid < 0){perror("fork is error");exit(1);}else{close(cfd);}}
}
多进程并发服务器带回收进程处理
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <stdio.h>
#include <error.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/wait.h>
#include <ctype.h>
#include <signal.h>#define SERIVER_PORT 9999void back_child(int signum)
{while((waitpid(0,NULL,WNOHANG))>0);return;
}int main(void)
{pid_t pid;int lfd, cfd;int ret, i;struct sockaddr_in myseriver;struct sockaddr_in myclient;int myclient_len = 0;char buf[100] = {0};lfd = socket(AF_INET, SOCK_STREAM, 0);if (lfd < 0){perror("socket is error");exit(1);}myseriver.sin_family = AF_INET;myseriver.sin_port = htons(SERIVER_PORT);myseriver.sin_addr.s_addr = htonl(INADDR_ANY);ret = bind(lfd, (struct sockaddr *)&myseriver, sizeof(myseriver));if (ret < 0){perror("bind is error");exit(1);}ret = listen(lfd, 128);if (ret < 0){perror("listen is error");exit(1);}myclient_len = sizeof(myclient);while (1){cfd = accept(lfd, (struct sockaddr *)&myclient, &myclient_len);if (cfd < 0){perror("accept is error");exit(1);}pid = fork();if (pid == 0){close(lfd);printf("childinit is success");while (1){ret = read(cfd, buf, sizeof(buf));if (ret == 0){close(cfd);exit(1);}for (i = 0; i < ret; i++)buf[i] = toupper(buf[i]);write(cfd, buf, ret);write(STDOUT_FILENO, buf, ret);}}else if (pid < 0){perror("fork is error");exit(1);}else{struct sigaction act;act.sa_handler = back_child;sigemptyset(&act.sa_mask); act.sa_flags = 0;ret = sigaction(SIGHUP, &act, NULL);if (ret != 0){perror("signal is error");}close(cfd);}}
}