- 多进程实现TCP并发服务器的实现流程:
- 一、自定义信号处理函数(sig_func函数):
void sig_func(int signum){wait(NULL);}
#include #include pid_t wait(int *wstatus);
- 二、创建套接字(socket函数):
- 通信域选择IPV4网络协议、套接字类型选择流式;
int sockfd = socket(AF_INET,SOCK_STREAM,0);
- 三、填充服务器的网络信息结构体:
- 1.定义网络信息结构体变量;
- 2.求出结构体变量的内存空间大小;
- 3.结构体清零;
- 4.使用IPV4网络协议;
- 5.在终端输入的IP地址,即
inet_addr(argv[1])
; - 6.在终端输入的网络字节序的端口号,即
htons(atoi(argv[2]))
;
struct sockaddr_in serveraddr; socklen_t serveraddrlen = sizeof(serveraddr);memset(&serveraddr,0,serveraddrlen); serveraddr.sin_family = AF_INET;serveraddr.sin_addr.s_addr = inet_addr(argv[1]);serveraddr.sin_port = htons(atoi(argv[2]));
- 四、套接字和服务器的网络信息结构体进行绑定(bind函数):
int ret = bind(sockfd,(struct sockaddr *)&serveraddr,serveraddrlen);
int ret1 = listen(sockfd, 5);
- 六、定义网络信息结构体变量保存来自客户端的消息(clientaddr):
struct sockaddr_in clientaddr;socklen_t clientaddr_len = sizeof(clientaddr);
- 七、注册信号处理函数回收资源( signal函数):
signal(SIGUSR1,sig_func);
#include typedef void (*sighandler_t)(int);sighandler_t signal(int signum, sighandler_t handler);
int acceptfd = accept(sockfd, (struct sockaddr *)&clientaddr, &clientaddr_len);
- 九、创建子进程(fork函数)用接收来自客户端的数据(recv函数)和给客户端发送应答消息(send函数),且双方通信结束后,给父进程发信号回收资源(kill函数):
if(-1 == (pid = fork())){perror("fork error");exit(-1);}else if(0 == pid){int nbytes = recv(acceptfd,buf,sizeof(buf),0);printf("客户端发来数据[%s]\n",buf);strcat(buf,"----k"); int ret2 = send(acceptfd,buf,sizeof(buf),0); kill(getppid(),SIGUSR1);}else if(0 < pid){close(accept_fd);}
#include #include int kill(pid_t pid, int sig);
close(sockfd);
#include #include #include #include #include #include #include #include #include #include #include #include void sig_func(int signum){wait(NULL);}int main(int argc, char const *argv[]){if(3 != argc){printf("Usage : %s \n",argv[0]);exit(-1);}int sockfd = socket(AF_INET,SOCK_STREAM,0);if(-1 == sockfd){perror("socket error");exit(-1);}struct sockaddr_in serveraddr;socklen_t serveraddr_len = sizeof(serveraddr);memset(&serveraddr,0,serveraddr_len);serveraddr.sin_family = AF_INET;serveraddr.sin_addr.s_addr = inet_addr(argv[1]);serveraddr.sin_port = htons(atoi(argv[2]));if(-1 == bind(sockfd,(struct sockaddr *)&serveraddr,serveraddr_len)){perror("bind error");exit(-1);}if(-1 == listen(sockfd,5)){perror("listen error");exit(-1);}struct sockaddr_in clientaddr;socklen_t clientaddr_len = sizeof(clientaddr);signal(SIGUSR1,sig_func);int accept_fd = 0;char buf[128] = {0};pid_t pid = 0;int nbytes = 0;while(true){if(-1 == (accept_fd = accept(sockfd,(struct sockaddr*)&clientaddr,&clientaddr_len))){perror("accept error");exit(-1);}if(-1 == (pid = fork())){perror("fork error");exit(-1);}else if(0 == pid){ close(sockfd);printf("客户端[%s : %d]连接到服务器\n",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));while(true){memset(buf,0,sizeof(buf));if(-1 == (nbytes = recv(accept_fd,buf,sizeof(buf),0))){perror("recv error");break;}else if(0 == nbytes){printf("客户端[%s : %d]断开了连接\n",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));break;}if(!strcmp(buf,"quit")){printf("客户端[%s : %d]退出了\n",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));break;}printf("客户端[%s : %d]发来消息[%s]\n",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port),buf);strcat(buf,"------k");if(-1 == send(accept_fd,buf,sizeof(buf),0)){perror("send error");exit(-1);}}close(accept_fd);kill(getppid(),SIGUSR1);exit(0);}else if(0 < pid){close(accept_fd);}}close(sockfd);return 0;}