TCP 通信并发服务器详解(附有案例代码)

一、多进程实现 TCP 通信并发服务器

1、多进程实现通信并发服务器思路

(1)一个父进程,多个子进程;

(2)父进程负责等待并接受客户端的连接;

(3)子进程:完成通信,接受一个客户端连接,就创建一个子进程用于通信。

2、多进程实现通信并发服务器案例代码

(1)客户端代码 client.c

C++音视频开发学习资料点击领取音视频开发(资料文档+视频教程+面试题)(FFmpeg+WebRTC+RTMP+RTSP+HLS+RTP)

// TCP通信的客户端#include #include #include #include #include  int main() {     // 1.创建套接字    int fd = socket(AF_INET, SOCK_STREAM, 0);    if(fd == -1) {        perror("socket");        exit(-1);    }     // 2.连接服务器端    struct sockaddr_in serveraddr;    serveraddr.sin_family = AF_INET;    inet_pton(AF_INET, "192.168.172.128", &serveraddr.sin_addr.s_addr);         //对应自己电脑的IP地址    serveraddr.sin_port = htons(9999);    int ret = connect(fd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));     if(ret == -1) {        perror("connect");        exit(-1);    }        // 3. 通信    char recvBuf[1024];    int i = 0;    while(1) {                sprintf(recvBuf, "data : %d
", i++);                // 给服务器端发送数据        write(fd, recvBuf, strlen(recvBuf)+1);          //+1是加上字符长结束字符         int len = read(fd, recvBuf, sizeof(recvBuf));        if(len == -1) {            perror("read");            exit(-1);        } else if(len > 0) {            printf("recv server : %s
", recvBuf);        } else if(len == 0) {            // 表示服务器端断开连接            printf("server closed...");            break;        }         sleep(1);    }     // 关闭连接    close(fd);     return 0;}

(2)服务端代码 server_process.c

#include #include #include #include #include #include #include #include  void recyleChild(int arg) {    while(1) {        int ret = waitpid(-1, NULL, WNOHANG);        if(ret == -1) {            // 所有的子进程都回收了            break;        }else if(ret == 0) {            // 还有子进程活着            break;        } else if(ret > 0){            // 被回收了            printf("子进程 %d 被回收了
", ret);        }    }} int main() {     struct sigaction act;    act.sa_flags = 0;    sigemptyset(&act.sa_mask);    act.sa_handler = recyleChild;     // 注册信号捕捉,释放资源,此时不能用wait,该函数会阻塞影响通信    sigaction(SIGCHLD, &act, NULL);         // 创建socket    int lfd = socket(PF_INET, SOCK_STREAM, 0);    if(lfd == -1){        perror("socket");        exit(-1);    }     struct sockaddr_in saddr;    saddr.sin_family = AF_INET;    saddr.sin_port = htons(9999);    saddr.sin_addr.s_addr = INADDR_ANY;     // 绑定    int ret = bind(lfd,(struct sockaddr *)&saddr, sizeof(saddr));    if(ret == -1) {        perror("bind");        exit(-1);    }     // 监听    ret = listen(lfd, 128);    if(ret == -1) {        perror("listen");        exit(-1);    }     // 不断循环等待客户端连接    while(1) {         struct sockaddr_in cliaddr;        int len = sizeof(cliaddr);        // 接受连接        int cfd = accept(lfd, (struct sockaddr*)&cliaddr, &len);        if(cfd == -1) {            if(errno == EINTR) {                continue;            }            perror("accept");            exit(-1);        }         // 每一个连接进来,创建一个子进程跟客户端通信        pid_t pid = fork();        if(pid == 0) {            // 子进程            // 获取客户端的信息            char cliIp[16];            inet_ntop(AF_INET, &cliaddr.sin_addr.s_addr, cliIp, sizeof(cliIp));            unsigned short cliPort = ntohs(cliaddr.sin_port);            printf("client ip is : %s, prot is %d
", cliIp, cliPort);             // 接收客户端发来的数据            char recvBuf[1024];            while(1) {                int len = read(cfd, &recvBuf, sizeof(recvBuf));                 if(len == -1) {                    perror("read");                    exit(-1);                }else if(len > 0) {                    printf("recv client : %s
", recvBuf);                } else if(len == 0) {                    printf("client closed....
");                    break;                }                write(cfd, recvBuf, strlen(recvBuf) + 1);            }            close(cfd);            exit(0);    // 退出当前子进程        }     }    close(lfd);    return 0;}

二、多线程实现 TCP 通信并发服务器

C++音视频开发学习资料点击领取音视频开发(资料文档+视频教程+面试题)(FFmpeg+WebRTC+RTMP+RTSP+HLS+RTP)

1、多进程实现通信并发服务器思路

(1)一个父线程,多个子线程;

(2)父线程负责等待并接受客户端的连接;

(3)子线程:完成通信,接受一个客户端连接,就创建一个子线程用于通信。

2、多线程实现通信并发服务器案例代码

#include #include #include #include #include #include  struct sockInfo {    int fd; // 通信的文件描述符    struct sockaddr_in addr;    pthread_t tid;  // 线程号}; struct sockInfo sockinfos[128]; void * working(void * arg) {    // 子线程和客户端通信   cfd 客户端的信息 线程号    // 获取客户端的信息    struct sockInfo * pinfo = (struct sockInfo *)arg;     char cliIp[16];    inet_ntop(AF_INET, &pinfo->addr.sin_addr.s_addr, cliIp, sizeof(cliIp));    unsigned short cliPort = ntohs(pinfo->addr.sin_port);    printf("client ip is : %s, prot is %d
", cliIp, cliPort);     // 接收客户端发来的数据    char recvBuf[1024];    while(1) {        int len = read(pinfo->fd, &recvBuf, sizeof(recvBuf));         if(len == -1) {            perror("read");            exit(-1);        }else if(len > 0) {            printf("recv client : %s
", recvBuf);        } else if(len == 0) {            printf("client closed....
");            break;        }        write(pinfo->fd, recvBuf, strlen(recvBuf) + 1);    }    close(pinfo->fd);    return NULL;} int main() {     // 创建socket    int lfd = socket(PF_INET, SOCK_STREAM, 0);    if(lfd == -1){        perror("socket");        exit(-1);    }     struct sockaddr_in saddr;    saddr.sin_family = AF_INET;    saddr.sin_port = htons(9999);    saddr.sin_addr.s_addr = INADDR_ANY;     // 绑定    int ret = bind(lfd,(struct sockaddr *)&saddr, sizeof(saddr));    if(ret == -1) {        perror("bind");        exit(-1);    }     // 监听    ret = listen(lfd, 128);    if(ret == -1) {        perror("listen");        exit(-1);    }     // 初始化数据    int max = sizeof(sockinfos) / sizeof(sockinfos[0]);    for(int i = 0; i < max; i++) {        bzero(&sockinfos[i], sizeof(sockinfos[i]));        sockinfos[i].fd = -1;        sockinfos[i].tid = -1;    }     // 循环等待客户端连接,一旦一个客户端连接进来,就创建一个子线程进行通信    while(1) {         struct sockaddr_in cliaddr;        int len = sizeof(cliaddr);        // 接受连接        int cfd = accept(lfd, (struct sockaddr*)&cliaddr, &len);         struct sockInfo * pinfo;        for(int i = 0; i < max; i++) {            // 从这个数组中找到一个可以用的sockInfo元素            if(sockinfos[i].fd == -1) {                pinfo = &sockinfos[i];                break;            }            if(i == max - 1) {                sleep(1);                i--;            }        }         pinfo->fd = cfd;        memcpy(&pinfo->addr, &cliaddr, len);         // 创建子线程        pthread_create(&pinfo->tid, NULL, working, pinfo);         pthread_detach(pinfo->tid);    }     close(lfd);    return 0;}
发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章