Bootstrap

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;
}

;