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;
}
相关推荐
寒水馨7 分钟前
Linux下载、安装llama.cpp-b10068(附安装包llama-b10068-bin-ubuntu-vulkan-x64.tar.gz)
linux·ubuntu·llm·llama·本地部署·llama.cpp·推理引擎
ziguo11223 小时前
C/C++ 错误处理全解:从 errno 到 C++ 异常
linux·c语言·c++·windows·visual studio
三8444 小时前
使用Samba/NFS实现文件共享/自动挂载共享目录/autofs自动挂载服务
linux·服务器·网络
高铭杰5 小时前
万物皆可KV(2)SurrealDB 存储布局分析
linux·服务器
无小道5 小时前
深入解析操作系统文件缓冲区:页缓存、基数树与f_pos的协同设计
linux·缓存·文件缓冲区
AOwhisky6 小时前
Linux(CentOS)系统管理入门笔记(第十二期)——系统管理工具与软件包管理(上篇):Cockpit 与 RPM 包管理
linux·运维·笔记·centos·云计算
寒水馨6 小时前
Linux下载、安装godot-4.7.1-stable(附安装包Godot_v4.7.1-stable_linux.x86_64.zip)
linux·游戏引擎·godot·游戏开发·2d游戏·3d游戏·godot engine
念恒123067 小时前
Socket编程UDP(中)
linux·网络协议·udp
深耕运维十八载云架构实务7 小时前
系统故障玄学之内存明明显示空闲,服务器却频繁卡顿卡死?拆解被忽略的 Linux 隐性内存陷阱
linux
糖果店的幽灵7 小时前
langgraph的流式执行
linux·运维·服务器·人工智能·langgraph