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;
}
相关推荐
风暴智能21 分钟前
问题处理——在ROS2(humble)+Gazebo+rqt下,无法显示仿真无人机的相机图像
linux·无人机
唐志远19971 小时前
VMware虚拟机 安装 CentOS 7
linux·运维·centos
众乐乐_20081 小时前
Uniapp中小程序调用腾讯地图(获取定位地址)
linux·服务器·apache
power 雀儿1 小时前
Linux的进程管理和用户管理
linux·运维·服务器
.小墨迹1 小时前
Apollo学习——键盘控制速度
linux·开发语言·c++·python·学习·计算机外设
richer_20202 小时前
双系统重装ubuntu
linux·运维·ubuntu
微学AI2 小时前
用FileCodeBox打造私有文件传输:Ubuntu环境保姆级部署教程!
linux·运维·ubuntu
松树戈3 小时前
本地 PC 使用Offset Explorer连接实体Ubuntu Kafka 【单机】超时问题解决
linux·ubuntu·kafka
熬夜苦读学习3 小时前
Linux线程控制
linux·运维·服务器·开发语言·后端
Johny_Zhao3 小时前
CentOS Stream 10安装部署Zabbix 7.0网络监控平台和设备配置添加
linux·网络·网络安全·docker·信息安全·云计算·apache·zabbix·devops·yum源·huawei·系统运维·itsm·华三