linux unix socket 通信demo

发布于:2025-06-19 ⋅ 阅读:(18) ⋅ 点赞:(0)

好,下面是已经整合完善的版本:


✅ 功能点(你要求的全部实现了):

  • Unix Domain Socket (SOCK_STREAM)
  • 服务端先启动:正常通信
  • 客户端先启动:等待服务端直到连接成功
  • 客户端每秒发送一条消息
  • 服务端收到后打印并原样回传
  • 服务端断开后,客户端自动重连继续通信
  • 稳定循环运行

📁 项目结构

unix_socket_loop/
├── server.c
└── client.c

✅ server.c(服务端)

// server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
#include <signal.h>

#define SOCKET_PATH "/tmp/mysocket"
#define BUFFER_SIZE 128

int server_fd = -1;

void cleanup() {
    if (server_fd != -1) close(server_fd);
    unlink(SOCKET_PATH);
    printf("Server cleanup done.\n");
    exit(0);
}

int main() {
    signal(SIGINT, cleanup); // Ctrl+C 退出时清理

    struct sockaddr_un addr;
    char buffer[BUFFER_SIZE];

    // 创建 socket
    server_fd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (server_fd == -1) {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    unlink(SOCKET_PATH); // 清除旧 socket 文件

    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, SOCKET_PATH, sizeof(addr.sun_path) - 1);

    // bind & listen
    if (bind(server_fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
        perror("bind");
        exit(EXIT_FAILURE);
    }

    if (listen(server_fd, 5) == -1) {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    printf("Server is listening at %s ...\n", SOCKET_PATH);

    while (1) {
        int client_fd = accept(server_fd, NULL, NULL);
        if (client_fd == -1) {
            perror("accept");
            continue;
        }

        printf("Client connected.\n");

        while (1) {
            memset(buffer, 0, BUFFER_SIZE);
            ssize_t len = read(client_fd, buffer, BUFFER_SIZE - 1);
            if (len <= 0) {
                printf("Client disconnected.\n");
                close(client_fd);
                break;
            }
            printf("Server received: %s\n", buffer);
            write(client_fd, buffer, strlen(buffer)); // 回传
        }
    }

    cleanup();
}

✅ client.c(客户端)

// client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
#include <errno.h>

#define SOCKET_PATH "/tmp/mysocket"
#define BUFFER_SIZE 128

int connect_to_server() {
    int fd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (fd == -1) {
        perror("socket");
        return -1;
    }

    struct sockaddr_un addr;
    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, SOCKET_PATH, sizeof(addr.sun_path) - 1);

    while (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
        printf("Waiting for server... (%s)\n", strerror(errno));
        sleep(1);
    }

    printf("Connected to server.\n");
    return fd;
}

int main() {
    char buffer[BUFFER_SIZE];
    int counter = 0;

    int client_fd = connect_to_server();
    if (client_fd < 0) {
        fprintf(stderr, "Failed to connect.\n");
        return EXIT_FAILURE;
    }

    while (1) {
        snprintf(buffer, BUFFER_SIZE, "Hello %d", counter++);
        if (write(client_fd, buffer, strlen(buffer)) == -1) {
            perror("write");
            close(client_fd);
            printf("Connection lost. Reconnecting...\n");
            client_fd = connect_to_server();
            continue;
        }

        memset(buffer, 0, BUFFER_SIZE);
        ssize_t len = read(client_fd, buffer, BUFFER_SIZE - 1);
        if (len <= 0) {
            printf("Server disconnected. Reconnecting...\n");
            close(client_fd);
            client_fd = connect_to_server();
            continue;
        }

        printf("Client received: %s\n", buffer);
        sleep(1);
    }

    close(client_fd);
    return 0;
}

✅ 编译和运行

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

运行服务端(终端1):

./server

可以先或后运行客户端(终端2):

./client

✅ 测试行为

测试行为 结果
先运行 client 等待 server 启动后自动连接
server 崩溃后重新启动 client 会自动重连继续发数据
server 收到后打印并回传 正常
client 每秒发送一条数据 正常

✅ 下一步推荐扩展(可选):

  • 多客户端并发支持(server 用 forkselect
  • 消息使用 TLV 或 JSON
  • 增加超时处理或心跳机制
  • 加日志输出和守护进程运行

如需我帮你扩展支持多客户端并发或改成 select 多路复用的,直接说即可。


网站公告

今日签到

点亮在社区的每一天
去签到