进程间通讯-套接字

发布时间:2023年12月25日

介绍

套接字(Socket)是用于进程间通信(IPC)的一种接口技术,它可以协调不同计算机上的进程间的通信,也就是基于网络的通信。同时,它也可以用于同一台计算机上的进程间通信。
套接字通信的方式有多种。以下是一些关于使用套接字进行进程间通信的基础知识:

  1. 套接字的类型

    • TCP套接字:传输控制协议(Transmission Control Protocol)提供面向连接、可靠的数据传输服务,确保数据包按照发送顺序到达接收端。
    • UDP套接字:用户数据报协议(User Datagram Protocol)提供无连接、不可靠但速度快的数据传输服务,不保证数据包的顺序或是否到达。
  2. 套接字的域

    • AF_INET:这是最常见的套接字域,用于Internet网络,基于IPv4地址。
    • AF_INET6:用于Internet网络,基于IPv6地址。
    • AF_UNIXAF_LOCAL:用于同一台机器上的进程间通信,使用文件路径作为地址。
  3. 套接字的创建
    在服务器端和客户端都需要创建套接字。这通常涉及到调用 socket() 系统调用,指定套接字的域、类型和协议。

  4. 服务器端操作

    • 绑定(bind):服务器端需要将其套接字与一个特定的IP地址和端口号关联起来。
    • 监听(listen):服务器端设置其套接字进入监听状态,等待客户端的连接请求。
    • 接受连接(accept):当有客户端发起连接请求时,服务器端接受这个连接,生成一个新的套接字用于与该客户端通信。
  5. 客户端操作

    • 连接(connect):客户端需要指定服务器的IP地址和端口号,然后发起连接请求。
  6. 数据传输

    • 发送(send/recv):通过调用 send()recv() 函数,服务器和客户端可以互相发送和接收数据。
    • 关闭连接:当通信完成时,双方可以关闭各自的套接字以结束连接。
  7. 错误处理
    在整个过程中,需要适当处理可能出现的错误,如连接失败、发送或接收数据时的错误等。

实现举例

服务器:

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

#define PORT 8080

int main() {
    int server_sock, client_sock;
    struct sockaddr_in server_addr, client_addr;
    socklen_t addr_len = sizeof(struct sockaddr_in);
    char message[100];

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

    // 设置服务器地址信息
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    // 绑定套接字到指定地址
    if (bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("binding failed");
        exit(EXIT_FAILURE);
    }

    // 开始监听连接请求
    if (listen(server_sock, 5) == -1) {
        perror("listening failed");
        exit(EXIT_FAILURE);
    }

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

    while (1) {
        // 接受客户端连接请求
        if ((client_sock = accept(server_sock, (struct sockaddr *)&client_addr, &addr_len)) == -1) {
            perror("accept failed");
            continue;
        }

        printf("Accepted connection from %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

        // 接收客户端发送的消息
        if (recv(client_sock, message, sizeof(message), 0) <= 0) {
            perror("recv failed");
            close(client_sock);
            continue;
        }

        printf("Received message: %s\n", message);

        // 发送回复消息给客户端
        strcpy(message, "Hello from server!");
        if (send(client_sock, message, strlen(message), 0) <= 0) {
            perror("send failed");
            close(client_sock);
            continue;
        }

        printf("Sent reply to client\n");

        // 关闭与客户端的连接
        close(client_sock);
    }

    // 关闭服务器套接字
    close(server_sock);

    return 0;
}

客户端:

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

#define SERVER_IP "127.0.0.1"
#define PORT 8080

int main() {
    int client_sock;
    struct sockaddr_in server_addr;
    char message[100];

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

    // 设置服务器地址信息
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    if (inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr) <= 0) {
        perror("invalid address / address not supported");
        exit(EXIT_FAILURE);
    }

    // 连接到服务器
    if (connect(client_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
        perror("connection failed");
        exit(EXIT_FAILURE);
    }

    printf("Connected to server at %s:%d\n", SERVER_IP, PORT);

    // 发送消息给服务器
    strcpy(message, "Hello from client!");
    if (send(client_sock, message, strlen(message), 0) <= 0) {
        perror("send failed");
        exit(EXIT_FAILURE);
    }

    printf("Sent message to server\n");

    // 接收服务器的回复
    if (recv(client_sock, message, sizeof(message), 0) <= 0) {
        perror("recv failed");
        exit(EXIT_FAILURE);
    }

    printf("Received reply from server: %s\n", message);

    // 关闭套接字
    close(client_sock);

    return 0;
}
示例说明

在这个例子中,服务器在本地主机的8080端口上监听连接请求。客户端连接到服务器,并发送一条消息。服务器接收消息,然后回复一条消息给客户端。最后,客户端接收回复并关闭连接。注意,你需要将SERVER_IP变量设置为你的服务器的实际IP地址(在这个例子中,我们使用的是本地回环地址127.0.0.1)。

总结

套接字通信提供了灵活且强大的机制来进行进程间通信,无论是本地还是网络环境。然而,它也相对复杂,需要处理诸如连接管理、数据流控制、错误处理等问题,所以我们再使用的时候,一定要评估好技术方案,是否有必要通过套接字实现进程通讯。

文章来源:https://blog.csdn.net/scy518/article/details/135190925
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。