Linux网络编程使用多进程实现服务器并发访问

一、概述

本攻略将详细讲解使用多进程实现Linux服务器并发访问的过程,具体涉及整体架构、代码实现以及代码调试等方面。该方法具有较高的灵活性和扩展性,适用于实现高并发,高可靠的服务器。

二、整体架构

多进程实现服务器并发访问的整体架构如下:

  1. 父进程负责创建并监听服务端socket,接收客户端的连接请求。

  2. 当有客户端连接请求到达时,父进程fork一个子进程,由该子进程与客户端进行数据交互。

  3. 如有需要,子进程可再次fork新的子进程,实现进一步的并发处理。

  4. 父进程负责回收已经处理完毕的子进程,防止出现“僵尸进程”。

三、代码实现

以下是一个简单的多进程服务器实现代码示例。

  1. 服务端代码
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>

#define PORT 8888
#define MAX_BUFFER_SIZE 1024

int main(int argc, char *argv[]) {
    int serverSocket, clientSocket, pid, readSize;
    struct sockaddr_in serverAddr, clientAddr;
    socklen_t addrLen = sizeof(clientAddr);
    char buffer[MAX_BUFFER_SIZE] = {0};

    // 创建服务端socket
    if ((serverSocket = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
        perror("Failed to create socket");
        exit(EXIT_FAILURE);
    }

    // 绑定socket到指定地址和端口
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = INADDR_ANY;
    serverAddr.sin_port = htons(PORT);
    if (bind(serverSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) < 0) {
        perror("Failed to bind");
        exit(EXIT_FAILURE);
    }

    // 开始监听连接请求
    if (listen(serverSocket, 5) < 0) {
        perror("Failed to listen");
        exit(EXIT_FAILURE);
    }

    printf("Server is listening on port %d\n", PORT);

    // 接收连接请求并处理
    while (1) {
        if ((clientSocket = accept(serverSocket, (struct sockaddr *) &clientAddr, &addrLen)) < 0) {
            perror("Failed to accept");
            exit(EXIT_FAILURE);
        }

        // 父进程fork一个子进程处理连接请求
        if ((pid = fork()) < 0) {
            perror("Failed to fork");
            exit(EXIT_FAILURE);
        } else if (pid == 0) {
            close(serverSocket); // 关闭父进程的监听socket
            printf("Client %s:%d is connected\n", inet_ntoa(clientAddr.sin_addr), clientAddr.sin_port);
            while((readSize = read(clientSocket, buffer, MAX_BUFFER_SIZE)) > 0) {
                printf("Received message from client %s:%d: %s", inet_ntoa(clientAddr.sin_addr), clientAddr.sin_port, buffer);
                write(clientSocket, "Server received your message", strlen("Server received your message"));
                memset(buffer, 0, MAX_BUFFER_SIZE);
            }
            printf("Client %s:%d disconnected\n", inet_ntoa(clientAddr.sin_addr), clientAddr.sin_port);
            close(clientSocket); // 关闭子进程的socket
            exit(EXIT_SUCCESS); // 终止子进程
        } else {
            close(clientSocket); // 关闭父进程对应客户端的连接
        }
    }
    return 0;
}
  1. 客户端代码
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

#define SERVER_ADDR "127.0.0.1"
#define PORT 8888
#define MAX_BUFFER_SIZE 1024

int main(int argc, char *argv[]) {
    int clientSocket;
    struct sockaddr_in serverAddr;
    char buffer[MAX_BUFFER_SIZE] = {0};

    // 创建客户端socket
    if ((clientSocket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("Failed to create socket");
        exit(EXIT_FAILURE);
    }

    // 设置服务端地址和端口
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(PORT);
    if (inet_pton(AF_INET, SERVER_ADDR, &serverAddr.sin_addr) <= 0) {
        perror("Invalid address/ Address not supported");
        exit(EXIT_FAILURE);
    }

    // 连接服务端
    if (connect(clientSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr)) < 0) {
        perror("Failed to connect");
        exit(EXIT_FAILURE);
    }

    // 发送消息
    while (fgets(buffer, MAX_BUFFER_SIZE, stdin) != NULL) {
        send(clientSocket, buffer, strlen(buffer), 0);
        memset(buffer, 0, MAX_BUFFER_SIZE);
        recv(clientSocket, buffer, MAX_BUFFER_SIZE, 0);
        printf("%s\n", buffer);
    }

    // 关闭客户端socket
    close(clientSocket);
    return 0;
}

四、代码调试

要在Linux环境下运行代码,可以使用gcc编译器进行编译,命令如下:

gcc -o server server.c
gcc -o client client.c

然后分别运行server和client可执行文件即可。

在运行过程中,可以使用netstat命令查看服务端监听的地址和端口,命令如下:

netstat -an | grep LISTEN

可以在客户端输入消息并发送,观察服务端是否正确接收并处理消息。

五、示例说明

  1. 实现FTP服务器。

在FTP服务器中,要求支持多个用户同时连接,对于每个用户的请求都进行互相独立的处理。使用多进程可以很方便地实现这个需求。

  1. 实现Web服务器。

Web服务器要求在高并发的情况下为客户端提供服务,使用多进程能方便地进行并发处理,提高服务器的并发能力和稳定性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Linux网络编程使用多进程实现服务器并发访问 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • java高并发ScheduledThreadPoolExecutor与Timer区别

    Java高并发ScheduledThreadPoolExecutor与Timer区别攻略 在开发过程中,我们经常需要实现定时任务,此时Java提供了两种处理定时任务的类:ScheduledThreadPoolExecutor和Timer。这两个类都可以完成定时任务的功能,本文将分别介绍它们的区别和使用场景。 ScheduledThreadPoolExecut…

    多线程 2023年5月17日
    00
  • c++11&14-多线程要点汇总

    C++11&14-多线程要点汇总 在C++11和C++14标准中,多线程相关的API得到了极大的增强和改善,本文将总结介绍其中一些重要的关键点。 1. std::thread std::thread是C++11中线程的关键类型,用于创建和管理线程。可以使用std::thread的构造函数来创建一个新的线程: #include <iostream…

    多线程 2023年5月17日
    00
  • Java并发工具辅助类代码实例

    针对“Java并发工具辅助类代码实例”的完整攻略,我们将从以下几个方面进行讲解: 什么是Java并发工具类? Java并发工具类的分类? Java并发工具类的使用方法? Java并发工具类的示例说明。 1. 什么是Java并发工具类? Java并发工具类是Java中提供的一些辅助类,用于实现线程安全的并行计算和多线程操作。这些工具类可以大大简化多线程编程的复…

    多线程 2023年5月17日
    00
  • shell脚本定时统计Nginx下access.log的PV并发送给API保存到数据库

    这里给出步骤如下: 步骤一:编写PV统计脚本 为了实现PV统计,我们需要编写脚本来扫描Nginx的access.log,统计PV并输出结果到一个文件中。假设我们将PV统计脚本命名为count_pv.sh,以下是一个示例代码: #!/bin/bash # 定义需要统计的日志文件路径 LOG_PATH="/var/log/nginx/access.lo…

    多线程 2023年5月17日
    00
  • PHP+shell实现多线程的方法

    针对 PHP+shell 实现多线程的方法,我可以提供以下完整攻略: 准备工作 在开始 PHP+shell 实现多线程操作之前,需要准备好以下工具: PHP解释器(Versions >= 5.3) shell命令行 Pcntl与pcntl_fork(PHP中的扩展) 实现方法 使用pcntl_fork()函数实现多进程操作: <?php $wor…

    多线程 2023年5月16日
    00
  • Go语言通过WaitGroup实现控制并发的示例详解

    下面是“Go语言通过WaitGroup实现控制并发的示例详解”的完整攻略。 简介 在并发编程中,我们经常需要协调多个goroutine的执行顺序,有可能需要等待一组goroutine全部执行完成才能进行下一步操作。Go语言提供了sync.WaitGroup来实现这样的控制,并发的方法。 sync.WaitGroup用于等待一组goroutine的执行,我们可…

    多线程 2023年5月16日
    00
  • 同步多线程(SMT)是什么意思?有什么作用?

    同步多线程(SMT)是指在计算机系统或处理器架构中支持在一个物理处理器核心上同时运行多个执行线程的技术。这是通过将单个物理处理器核心的资源分配给多个线程来实现的,使得每个线程都可以访问并执行指令,从而提高处理器的吞吐量和执行能力。SMT的实质是在物理上使用了多个逻辑CPU,在逻辑CPU之间切换来掩盖处理器中资源的闲置,从而提高了处理能力。 SMT的主要优点是…

    多线程 2023年5月17日
    00
  • springmvc配置线程池Executor做多线程并发操作的代码实例

    下面是springmvc配置线程池Executor做多线程并发操作的完整攻略。 1. 简介 在Web开发中,使用多线程可以提高程序的并发性和效率,但是传统的Java多线程实现起来较为麻烦。而在SpringMVC框架中,可以使用线程池Executor来简单方便地实现多线程操作。 2. 步骤 2.1. 添加依赖 在pom.xml文件中添加以下依赖: <de…

    多线程 2023年5月16日
    00
合作推广
合作推广
分享本页
返回顶部