多线程|多进程|高并发网络编程

2023年 9月 26日 35.9k 0

一.多进程并发服务器

多进程并发服务器是一种经典的服务器架构,它通过创建多个子进程来处理客户端连接,从而实现并发处理多个客户端请求的能力。

概念:

  • 服务器启动时,创建主进程,并绑定监听端口。
  • 当有客户端连接请求时,主进程接受连接,并创建一个子进程来处理该客户端连接。
  • 子进程与客户端进行通信,处理请求和发送响应。
  • 主进程继续监听新的连接请求。
  • 子进程完成任务后,可以选择终止或继续处理其他连接,根据需求选择是否重复循环。
  • 优点:

  • 高并发处理能力:每个子进程都可以独立地处理一个客户端连接,利用多核处理器的优势,实现高并发处理能力,提高服务器的吞吐量。
  • 稳定性:每个子进程都是独立的,一个进程出现问题不会影响其他进程,提高了服务器的稳定性和容错能力。
  • 简单直观:采用多进程模型实现并发服务器相对简单,代码可读性高,易于理解和维护。
  • 跨平台:多进程并发服务器概念适用于各种操作系统,不仅限于Linux平台。
  • 缺点:

  • 高资源消耗:每个子进程都需要独立的资源,包括内存、文件描述符等,当并发连接数较高时,会消耗大量的系统资源。
  • 进程间通信:各个子进程之间的通信需要额外的机制,例如管道、共享内存等,增加了复杂性。
  • 上下文切换开销:进程间切换的开销相对较大,会影响性能。
  • 调试困难:由于每个子进程独立执行,调试和定位问题可能会变得复杂。
  • 综上所述,多进程并发服务器能够满足高并发处理需求,并具有稳定性和简单性等优点。然而,它也存在资源消耗较高和调试困难等缺点,根据实际需求和应用场景选择合适的服务器架构是很重要的。

    案例

    利用多进程,在TCP通信的基础上,实现服务器可以同时连接多个客户端。实现大小写转换。

    service.c

    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include

    void handler(int sig)
    {
    if (sig == SIGCHLD)
    {
    while(waitpid(0,NULL,WNOHANG)>0);
    }
    }
    int main(int argc, char const *argv[])
    {
    //1.建立socket套接字
    int socked = socket(AF_INET, SOCK_STREAM, 0);
    if (socked < 0)
    {
    perror("socket is err");
    return -1;
    }

    //2.bind绑定服务器ip和端口号
    struct sockaddr_in saddr, caddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(atoi(argv[1]));
    saddr.sin_addr.s_addr = inet_addr("0.0.0.0");
    int len = sizeof(caddr);
    int rev = bind(socked, (struct sockaddr *)(&saddr), sizeof(saddr));
    if (rev < 0)
    {
    perror("bind is err");
    return 0;
    }

    //3.listen设置最大同时链接数量
    rev = listen(socked, 32);
    if (rev < 0)
    {
    perror("rev is err");
    return 0;
    }

    //4.建立子进程负责服务器给客户端发送消息,并且主进程不结束,此进程不结束
    char buf[1024] = {0};
    int size=0;
    while (1)
    {
    int acceptfd = accept(socked, (struct sockaddr *)(&caddr), &len);
    if (acceptfd < 0)
    {
    perror("accept is err");
    return 0;
    }
    pid_t pid = fork();
    if (pid < 0)
    {
    perror("pid is err");
    return 0;
    }
    else if (pid == 0)
    {
    //子进程,每个子进程维护一个客户端
    //不许要监听,直接关掉
    close(socked);
    while (1)
    {

    int flage = recv(acceptfd, buf, sizeof(buf), 0);
    if (flage < 0)
    {
    perror("recv is err");
    }
    else if (flage == 0)
    {
    printf("ip:%s is close\n", inet_ntoa(caddr.sin_addr));
    close(acceptfd);
    break;
    }
    else
    {
    size = strlen(buf);

    for (int i = 0; i = 'a' && buf[i] acceptfd;
    struct sockaddr_in caddr = cl->caddr;
    while (1)
    {
    int flage = recv(acceptfd, buf, sizeof(buf), 0);
    if (flage < 0)
    {
    perror("recv is err");
    }
    else if (flage == 0)
    {
    printf("ip:%s is close\n", inet_ntoa(caddr.sin_addr));
    close(acceptfd);
    break;
    }
    else
    {
    size = strlen(buf);

    for (int i = 0; i = 'a' && buf[i]

    相关文章

    服务器端口转发,带你了解服务器端口转发
    服务器开放端口,服务器开放端口的步骤
    产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
    如何使用 WinGet 下载 Microsoft Store 应用
    百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
    百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

    发布评论