Linux TCP Socket实现进程间通信

王景迁 / 2023-07-30 / 原文

Linux Socket由内核实现。

服务端
初始化Socket->绑定地址和端口->监听端口->accept阻塞等待客户端连接->处理请求并响应
客户端
初始化Socket->连接服务端->发送请求->读取数据->关闭连接

common.h

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

#define PORT 3000
#define MAX_CHARS 1000
#define MAX_CONNECTIONS 5

client.c

#include "common.h"

int main(int argc, char **argv)
{
    int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (socket_fd == -1)
    {
        printf("create socket error: %s\n", strerror(errno));
        exit(1);
    }

    struct sockaddr_in servaddr;
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(PORT);
    inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);

    if (connect(socket_fd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)
    {
        printf("connect error: %s\n", strerror(errno));
        exit(1);
    }

    char msg[MAX_CHARS];
    printf("send:\n");
    fgets(msg, MAX_CHARS, stdin);
    if (send(socket_fd, msg, strlen(msg), 0) == -1)
    {
        printf("send error: %s\n", strerror(errno));
        exit(1);
    }

    char buf[MAX_CHARS];
    int n;
    n = recv(socket_fd, buf, MAX_CHARS, 0);
    if (n == -1)
    {
        perror("receive error");
        exit(1);
    }

    buf[n] = '\0';
    printf("receive: %s", buf);

    close(socket_fd);
    exit(0);
}

server.c

#include "common.h"

int main(int argc, char **argv)
{
    int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (socket_fd == -1)
    {
        printf("create socket error: %s\n", strerror(errno));
        exit(1);
    }

    struct sockaddr_in servaddr;
    servaddr.sin_family = AF_INET;
    // INADDR_ANY表示本机地址
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port = htons(PORT);

    if (bind(socket_fd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)
    {
        printf("bind socket error: %s\n", strerror(errno));
        exit(1);
    }

    if (listen(socket_fd, MAX_CONNECTIONS) == -1)
    {
        printf("listen socket error: %s\n", strerror(errno));
        exit(1);
    }

    printf("handle client request\n");
    while (1)
    {
        int connect_fd = accept(socket_fd, (struct sockaddr *)NULL, NULL);
        if (connect_fd == -1)
        {
            printf("accept socket error: %s", strerror(errno));
            continue;
        }

        int n;
        char buff[1000];
        n = recv(connect_fd, buff, MAX_CHARS, 0);
        // 末尾设置字符数组结束标志
        buff[n] = '\0';
        printf("receive: %s", buff);

        // 创建子进程来处理请求
        if (!fork())
        {
            char resp[100] = "handle complete\n";
            if (send(connect_fd, resp, strlen(resp), 0) == -1)
                perror("send error");
            close(connect_fd);
            exit(0);
        }

        close(connect_fd);
    }

    close(socket_fd);
    exit(0);
}