Linux网络编程----使用多进程实现并发服务器

一.前言

要实现tcp通信服务器处理并法的任务,使用多线程或者多线程来解决

这里我们使用多进程来实现:

1.一个父进程,多个子进程

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

3.子进程:完成通信,接收一个客户端的连接,就创建一个子进程来通信

二.代码实例实现

服务端

复制代码
#include <stdio.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <wait.h>
#include <errno.h>
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,被回收了\n",ret);
        }
    }
}
int main()
{   
    //注册信号捕捉
    struct sigaction act;
    act.sa_flags = 0;
    sigemptyset(&act.sa_mask);
    act.sa_handler = recyleChild;
    sigaction(SIGCHLD,&act,0);


    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd == -1)
    {
        perror("socket");
        exit(-1);
    }
    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons(8000);

    if(bind(sockfd,(struct sockaddr*)&server,sizeof(server))==-1)
    {
        perror("bind");
        exit(-1);
    }

    if(listen(sockfd, 8) == -1)
    {
        perror("listen");
        exit(-1);
    }

    int client_fd;
    struct sockaddr_in client_addr;
    int len = sizeof(client_addr);
    while(1)
    {
        client_fd = accept(sockfd,(struct sockaddr*)&client_addr,&len);
        if(client_fd == -1)
        {
            if(errno == EINTR)
            {
                //产生了中断
                continue;
            }
            perror("accept");
            exit(-1);
        }

        //每一个连接进来就创建一个子进程来根客户端通信
        pid_t pid = fork();
        if(pid == -1)
        {
            perror("fork");
        }
        else if(pid == 0)
        {
            //子进程
            char client_ip[16];
            inet_ntop(AF_INET,(const void *)&client_addr.sin_addr.s_addr,client_ip,sizeof(client_ip));
            unsigned short client_port = ntohs(client_addr.sin_port);
            printf("客户端ip is : %s, port is : %d\n",client_ip,client_port);
            //接收客户端发来的信息
            char recvBuf[1024];
            while(1)
            {
                memset(recvBuf,0,sizeof(recvBuf));
                int data_len = read(client_fd,recvBuf,sizeof(recvBuf));
                if(data_len == -1)
                {
                    perror("read");
                    break;
                }
                else if(data_len > 0)
                {
                    printf("recv client data:%s\n",recvBuf);
                    write(client_fd,recvBuf,strlen(recvBuf));
                }
                else if(data_len == 0)
                {
                    printf("客户端断开连接\n");
                    break;
                }
            }
            close(client_fd);
            exit(0); //退出当前子进程
        }

    }
    close(sockfd);
    return 0;
}

客户端

复制代码
#include <stdio.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>


int main()
{
    int sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd == -1)
    {
        perror("socket");
        exit(-1);
    }
    struct sockaddr_in client;
    client.sin_family = AF_INET;
    client.sin_addr.s_addr = inet_addr("127.0.0.1");
    client.sin_port = htons(8000);
    if(connect(sockfd,(const struct sockaddr*)&client,sizeof(client)) == -1)
    {
        perror("connect");
        exit(-1);
    }

    //写
    char *client_send_data;
    char client_recv_buf[1024];
    int len;
    while(1)
    {
        printf("亲爱的用户,请发送你要发送给服务器的数据:");
        scanf("%s",client_send_data);
        len = write(sockfd,client_send_data,strlen(client_send_data));
        if(len == -1)
        {
            perror("write");
            break;
        }

        memset(client_recv_buf,0,sizeof(client_recv_buf));
        len = read(sockfd,client_recv_buf,sizeof(client_recv_buf));
        if(len == -1)
        {
            perror("read");
            break;
        }
        else if(len > 0)
        {
            printf("接收到服务器端的回射数据:%s\n",client_recv_buf);
        }
        else if(len == 0)
        {
            printf("服务器断开连接\n");
            break;
        }
        sleep(1);
    }
    close(sockfd);
    return 0;
}
相关推荐
deeper_wind1 小时前
k8s-容器化部署论坛和商城服务(小白的“升级打怪”成长之路)
linux·运维·容器·kubernetes
勇往直前plus1 小时前
VMware centos磁盘容量扩容教程
linux·运维·centos
政安晨3 小时前
Ubuntu 服务器无法 ping 通网站域名的问题解决备忘 ——通常与网络配置有关(DNS解析)
linux·运维·服务器·ubuntu·ping·esp32编译服务器·dns域名解析
路溪非溪4 小时前
嵌入式Linux驱动开发杂项总结
linux·运维·驱动开发
Neolock5 小时前
Linux应急响应一般思路(三)
linux·web安全·应急响应
被遗忘的旋律.6 小时前
Linux驱动开发笔记(七)——并发与竞争(上)——原子操作
linux·驱动开发·笔记
轻松Ai享生活6 小时前
minidump vs core dump
linux
轻松Ai享生活7 小时前
详细的 Linux 常用文件系统介绍
linux
张童瑶7 小时前
Linux 离线安装lrzsz(rz、sz上传下载小插件)
linux·运维·centos
十五年专注C++开发8 小时前
通信中间件 Fast DDS(二) :详细介绍
linux·c++·windows·中间件·fastdds