Linux下实现多进程Socket通信功能的示例代码

 更新时间:2025年06月03日 08:52:27   作者:酷爱码Linux  
Socket通信基于客户端-服务器架构,分为两种主要模式,TCP协议(面向连接)和UDP协议(无连接),下面我们就来看看Linux下实现多进程Socket通信功能具体实现方法吧

一、多进程Socket通信的基本原理

1. Socket通信模型

Socket通信基于客户端-服务器架构,分为以下两种主要模式:

  • TCP协议(面向连接):通过三次握手建立稳定连接,适用于可靠数据传输(如文件传输、Web服务)。
  • UDP协议(无连接):直接发送数据包,无需建立连接,适用于实时性要求高的场景(如视频流、在线游戏)。

在多进程模型中,服务器通过fork()系统调用为每个客户端连接创建独立的子进程,每个子进程独立处理一个客户端请求,互不干扰。

二、Linux下Socket编程的核心函数

1. 关键函数及其作用

以下函数是实现Socket通信的基础:

函数名功能描述
socket()创建套接字,返回文件描述符。
bind()将套接字绑定到指定的IP地址和端口。
listen()将套接字设为监听状态,等待客户端连接。
accept()接受客户端连接请求,返回新的套接字用于通信。
connect()客户端主动连接服务器。
send()/recv()发送和接收数据。
close()关闭套接字。
fork()创建子进程,用于处理客户端连接。

2. 多进程模型的核心流程

服务器初始化:创建监听套接字,绑定地址和端口,进入监听状态。

客户端连接:服务器通过accept()接受连接,创建子进程处理该连接。

数据交互:子进程与客户端通过send()/recv()进行通信。

资源回收:子进程处理完毕后退出,父进程通过wait()回收资源。

三、多进程Socket通信的实现步骤

1. 服务器端实现

(1)创建监听套接字

#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    int server_fd, new_socket;
    struct sockaddr_in address;
    int addrlen = sizeof(address);

    // 创建TCP套接字
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd == 0) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }

    // 绑定地址和端口
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;  // 监听所有IP
    address.sin_port = htons(8080);        // 端口8080
    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
        perror("Bind failed");
        close(server_fd);
        exit(EXIT_FAILURE);
    }

    // 监听连接请求
    if (listen(server_fd, 10) < 0) {
        perror("Listen failed");
        close(server_fd);
        exit(EXIT_FAILURE);
    }

    printf("Server is listening on port 8080...\n");

(2)接受连接并创建子进程

    while (1) {
        // 接受客户端连接
        new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen);
        if (new_socket < 0) {
            perror("Accept failed");
            continue;
        }

        // 创建子进程处理连接
        pid_t pid = fork();
        if (pid < 0) {
            perror("Fork failed");
            close(new_socket);
            continue;
        } else if (pid == 0) {
            // 子进程:处理客户端请求
            char buffer[1024] = {0};
            read(new_socket, buffer, 1024);
            printf("Received from client: %s\n", buffer);

            // 发送响应
            const char *response = "Hello from server!";
            write(new_socket, response, strlen(response));
            close(new_socket);
            exit(0);  // 子进程结束
        } else {
            // 父进程:关闭新套接字,继续监听
            close(new_socket);
        }
    }

    // 关闭监听套接字
    close(server_fd);
    return 0;
}

2. 客户端实现

#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    int sock = 0;
    struct sockaddr_in serv_addr;

    // 创建套接字
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        perror("Socket creation failed");
        exit(EXIT_FAILURE);
    }

    // 设置服务器地址
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(8080);
    serv_addr.sin_addr.s_addr = INADDR_ANY;

    // 连接服务器
    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
        perror("Connection failed");
        close(sock);
        exit(EXIT_FAILURE);
    }

    // 发送请求
    const char *request = "Hello from client!";
    send(sock, request, strlen(request), 0);

    // 接收响应
    char buffer[1024] = {0};
    read(sock, buffer, 1024);
    printf("Server response: %s\n", buffer);

    // 关闭套接字
    close(sock);
    return 0;
}

四、多进程模型的关键注意事项

1. 僵尸进程处理

当子进程结束后,若父进程未调用wait()回收资源,子进程会变为僵尸进程(Zombie)。为避免此问题,可在父进程中注册SIGCHLD信号处理函数:

#include <signal.h>

void sigchld_handler(int sig) {
    int status;
    while (waitpid(-1, &status, WNOHANG) > 0);  // 清理所有僵尸进程
}

// 在服务器主函数中注册信号处理
signal(SIGCHLD, sigchld_handler);

2. 资源泄漏预防

文件描述符关闭:子进程在处理完连接后必须关闭new_socket,父进程也需关闭new_socket以避免资源浪费。

错误处理:对fork()、socket()等函数调用结果进行检查,确保异常情况下的程序健壮性。

3. 性能优化建议

限制最大进程数:通过设置ulimit -n调整系统文件描述符上限,避免过多进程导致系统资源耗尽。

结合I/O多路复用:对于高并发场景,可结合epoll或select实现更高效的事件驱动模型。

五、多进程模型的优缺点分析

1. 优点

  • 简单直观:每个客户端独立处理,逻辑清晰,易于调试和维护。
  • 隔离性高:子进程崩溃不影响父进程或其他子进程。

2. 缺点

  • 资源消耗大:每个进程占用独立的内存空间,进程创建和销毁成本较高。
  • 不适合超大规模并发:在万级并发场景下,进程数量可能导致系统性能下降。

六、总结

多进程Socket通信是Linux环境下实现高并发服务的经典方案,通过fork()为每个客户端创建独立进程,能够有效处理多个客户端请求。然而,开发者需注意僵尸进程、资源泄漏等问题,并根据实际需求选择合适的并发模型(如多线程、事件驱动)。通过本文的代码示例和原理讲解,读者可以快速掌握多进程Socket通信的实现方法,并在此基础上扩展更复杂的应用场景(如文件传输、聊天室等)。

实践建议:

  • 使用valgrind工具检测内存泄漏。
  • 在服务器端增加日志记录功能,便于调试和监控。
  • 结合systemd或supervisord实现服务的自动重启和管理。

通过不断优化和扩展,多进程Socket通信模型将成为构建高性能网络应用的重要基石。

到此这篇关于Linux下实现多进程Socket通信功能的示例代码的文章就介绍到这了,更多相关Linux多进程Socket通信内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Ubuntu下安装Chrome的方法分享

    Ubuntu下安装Chrome的方法分享

    本文给大家分享的是Ubuntu下安装Chrome的方法,安装的过程中发现还是挺麻烦的,就记录下来推荐给大家,有需要的小伙伴可以参考下。
    2015-04-04
  • 详解Ubuntu16.04下Hadoop 2.7.3的安装与配置

    详解Ubuntu16.04下Hadoop 2.7.3的安装与配置

    本篇文章主要介绍了详解Ubuntu16.04下Hadoop 2.7.3的安装与配置,具有一定的参考价值,有兴趣的可以了解一下。
    2017-01-01
  • linux安装全中文管理面板教程(php+mysql)

    linux安装全中文管理面板教程(php+mysql)

    这篇文章主要介绍了linux安装全中文管理面板教程(php+mysql运行环境),需要的朋友可以参考下
    2014-09-09
  • linux下实时查看tomcat运行日志的方法

    linux下实时查看tomcat运行日志的方法

    下面小编就为大家带来一篇linux下实时查看tomcat运行日志的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起 小编过来看看吧
    2016-11-11
  • Linux环境下部署Consul集群

    Linux环境下部署Consul集群

    这篇文章介绍了Linux环境下部署Consul集群的方法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • Linux安装NodeJs并配合Nginx实现反向代理

    Linux安装NodeJs并配合Nginx实现反向代理

    本篇文章主要介绍了Linux安装NodeJs并配合Nginx实现反向代理,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2016-11-11
  • 在Linux中使用Vundle管理Vim插件的方法

    在Linux中使用Vundle管理Vim插件的方法

    Vim缺乏默认的插件管理器,所有插件的文件都散布在~/.vim下的几个文件夹中,插件的安装与更新与删除都需要自己手动来,既麻烦费事,又可能出现错误。下面这篇文章主要给大家介绍了关于在Linux中使用Vundle管理Vim插件的方法,需要的朋友可以参考下。
    2018-04-04
  • Ubuntu 18.04中截图工具shutter的编辑按钮不可用的解决办法

    Ubuntu 18.04中截图工具shutter的编辑按钮不可用的解决办法

    Shutter是一个由第三方提供的在Ubuntu上运行的截图工具。这篇文章主要介绍了Ubuntu 18.04中截图工具shutter的编辑按钮不可用的解决办法及Ubuntu18.04 截图工具推荐,需要的朋友可以参考下
    2018-08-08
  • ssh远程登陆没有用户名和主机名的解决方法

    ssh远程登陆没有用户名和主机名的解决方法

    这篇文章主要给大家分享了ssh远程登陆没有用户名和主机名的解决方法,文中介绍的非常详细,相信对大家具有一定的参考价值,需要的朋友们下面来一起看看吧。
    2017-03-03
  • Linux系统下安装jdbc与tomcat的图文教程

    Linux系统下安装jdbc与tomcat的图文教程

    本文通过图文并茂的形式给大家介绍了Linux系统下安装jdbc与tomcat的方法,本文给大家介绍的非常详细,具有参考借鉴价值,需要的朋友参考下吧
    2018-01-01

最新评论