共计 2601 个字符,预计需要花费 7 分钟才能阅读完成。
Linux 多进程 CS 服务器简单实现
server 端
- 多进程实现多用户连接,即每个用户一个连接,这里仍然用 server 将收到的字符串转大写后返回给客户端。
- 代码实现
#include <stdio.h> #include <string.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <ctype.h> #include <stdlib.h> #include <sys/wait.h> #define SERV_IP "127.0.0.1" #define SERV_PORT 8000 void wait_child(int signo)// 回收子进程函数 {while(waitpid(0, NULL, WNOHANG)>0); return; } int main(int argc,char *argv[]) {pid_t pid;// 进程 ID int sfd, cfd;// 接收连接的 sfd, 和 client 通讯的 cfd struct sockaddr_in serv_addr, clie_addr;// 创建服务器和客户端结构体 socklen_t clie_addr_len;// 客户端结构体长度 char buf[BUFSIZ], clie_IP[BUFSIZ];//buf 存放接收到的数据 int n , i;// 读取的数据数 n, 循环因子 i sfd = socket(AF_INET, SOCK_STREAM, 0);// 创建套接字 bzero(&serv_addr, sizeof(serv_addr));// 清零 serv_addr.sin_family = AF_INET;// 设置协议族为 IPv4 serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 设置网卡为本地任何有效网卡 //inet_pton(AF_INET, SERV_IP, &serv_addr.sin_addr.s_addr); serv_addr.sin_port = htons(SERV_PORT);// 设置端口 bind(sfd, (struct sockaddr * )&serv_addr, sizeof(serv_addr));// 设置套接字与 sfd 关联 listen(sfd, 128);// 设置未完成 accept 的最大数量. 开始监听. while(1)// 循环接收客户端连接 {clie_addr_len = sizeof(clie_addr);// 初始化客户端结构体长度 cfd = accept(sfd, (struct sockaddr *)&clie_addr, &clie_addr_len);// 接收客户端连接 printf("client IP:%s, port:%d\n", inet_ntop(AF_INET, &clie_addr.sin_addr.s_addr, clie_IP, sizeof(clie_IP)), ntohs(clie_addr.sin_port)); pid = fork();// 创建新进程 if(pid< 0)// 出错 {perror("fork error"); exit(1); } else if(pid == 0)// 子进程 {close(sfd);// 子进程中先关闭父进程文件描述符 break; } else if(pid>0)// 父进程 {close(cfd);// 父进程中先关闭子进程文件描述符 signal(SIGCHLD, wait_child);// 注册信号用于回收已结束的子进程 } } if(pid == 0)// 以下是子进程真正的业务处理部分 {while(1)// 循环处理客户端业务 {n = read(cfd, buf, sizeof(buf)); if(n == 0)// 如果 read 返回 0, 说明客户端已断开连接 {close(cfd);// 关闭客户端文件描述符 return 0; } else if(n == -1)// 出错 {perror("read error"); exit(1); } else {write(STDOUT_FILENO, buf, n); for(i= 0; i< n;++i) {buf[i] = toupper(buf[i]); } write(cfd, buf, n); } } } return 0; }
client 端
- 连接 server 端,发送字符串,将收到的字符串打印出来(即:与 nc 命令功能相同)。
- 代码实现
#include <stdio.h> #include <string.h> #include <unistd.h> #include <netinet/in.h> #include <arpa/inet.h> #define MAXLINE 8192 #define SERV_PORT 8000 int main(int argc,char *argv[]) {struct sockaddr_in servaddr; char buf[MAXLINE]; int sockfd, n; sockfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr); servaddr.sin_port = htons(SERV_PORT); connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); while(fgets(buf, MAXLINE, stdin)!=NULL) {write(sockfd, buf, strlen(buf)); n =Read(sockfd, buf, MAXLINE); if(n ==0) {printf("the other side has been closed.\n"); break; } else write(STDOUT_FILENO, buf, n); } close(sockfd); return 0; }
测试结果
- 可以实现多个客户端同时连接服务器,服务器每接受一个客户就创建一个子进程,用户端断开后,进程由父进程自动回收子进程。
存在问题
- 仅供学习参考,未进行错误处理。多用户连接时,可能产生读写中断干扰。
本文永久更新链接地址 :http://www.linuxidc.com/Linux/2018-01/150035.htm
正文完
星哥玩云-微信公众号