当前位置: 首页 > article >正文

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


http://www.kler.cn/a/410000.html

相关文章:

  • 电脑开启虚拟化的方法
  • 设计模式之 模板方法模式
  • TensorFlow如何调用GPU?
  • 【华为】配置VXLAN构建虚拟网络实现相同网段互通(静态方式)
  • vue中el-table合并单元格
  • CSS clamp() 函数:构建更智能的响应式设计
  • 【Leetcode 每日一题】146. LRU 缓存(c++)
  • Django快速上手:从零到一构建Web应用
  • HTMLCSS:彩色灵动气泡效果
  • Redis的管道操作
  • 小程序-基于java+SpringBoot+Vue的农场管理系统设计与实现
  • I.MX6U 裸机开发20. DDR3 内存知识
  • 模拟器多开限制ip,如何设置单窗口单ip,每个窗口ip不同
  • Oracle RMAN克隆数据库(同主机)
  • 硬件基础22 反馈放大电路
  • 深入解析信号量:定义与环形队列生产消费模型剖析
  • 深入理解B-树与B+树:数据结构中的高效索引利器
  • node.js.抓取代理ip(提供参考)
  • Python网络爬虫基础
  • mac 安装node提示 nvm install v14.21.3 failed可能存在问题
  • 华为ENSP--IP编址及静态路由配置
  • Python3 WebUI自动化总篇:Python3+Selenium+Pytest+Allure+ Jenkins webUI自动化框架
  • AddIPAddress添加临时IP后,socket bind失败
  • 记录两次Unity编辑器和真机表现不符的情况,引用丢失等
  • 英语知识在线平台:Spring Boot框架实践
  • k8s篇之flannel网络模型详解