You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

重启服务器遇bind()错误:Address already in use问题求助

AF_UNIX套接字重启绑定失败问题排查与解决

问题根源分析

  • 结构体混用错误:你创建的是AF_UNIX域套接字,但代码中错误使用了struct sockaddr_in(该结构体用于IPv4网络套接字),UNIX域套接字必须使用struct sockaddr_un结构体。
  • SO_REUSEADDR无效:这个套接字选项仅对TCP/UDP网络套接字生效,对基于文件系统路径的UNIX域套接字没有作用,添加它解决不了问题。
  • 套接字文件残留:绑定UNIX域套接字时,系统会在指定路径生成一个套接字文件,程序退出时(尤其是异常退出)该文件不会自动删除,再次绑定同一路径就会触发"Address already in use"错误。

解决方案

1. 替换正确的地址结构体

将代码中的struct sockaddr_in替换为struct sockaddr_un,并设置合法的文件路径(比如/tmp/unix_socket)。

2. 绑定前清理残留文件

在调用bind()之前,先调用unlink()删除可能存在的旧套接字文件,确保路径可用。

3. 程序退出时清理套接字文件

无论是正常退出还是异常终止,都要删除套接字文件,避免残留。可以通过注册信号处理函数来捕获异常退出信号,执行清理操作。

修改后的服务端代码

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <signal.h>
#include <string.h>

#define UNIX_SOCKET_PATH "/tmp/unix_socket"

// 信号处理函数,用于异常退出时清理套接字文件
void cleanup(int sig) {
    unlink(UNIX_SOCKET_PATH);
    _exit(0);
}

int main()
{
    int sd, connection_fd;
    int bind_status;
    int listen_status;
    socklen_t client_size;

    struct sockaddr_un server, client;

    int readBytes, writeBytes;
    char data[200];

    // 注册信号处理,捕获中断信号
    signal(SIGINT, cleanup);
    signal(SIGTERM, cleanup);

    sd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (sd < 0) {
        perror("Error while creating socket for server side");
        return 1;
    }

    printf("Server socket successfully created\n");

    // 初始化UNIX域套接字地址结构体
    server.sun_family = AF_UNIX;
    strncpy(server.sun_path, UNIX_SOCKET_PATH, sizeof(server.sun_path) - 1);

    // 绑定前清理残留的套接字文件
    unlink(UNIX_SOCKET_PATH);

    bind_status = bind(sd, (struct sockaddr *)&server, sizeof(server));
    if (bind_status < 0) {
        perror("Error in binding address to socket");
        close(sd);
        return 1;
    }
    printf("Successfully binded the UNIX socket path\n");

    listen_status = listen(sd, 2);
    if (listen_status < 0) {
        perror("Error while listening for connections");
        unlink(UNIX_SOCKET_PATH);
        close(sd);
        return 1;
    }

    printf("Now listening for connections\n");

    client_size = sizeof(client);
    connection_fd = accept(sd, (struct sockaddr *)&client, &client_size);
    if (connection_fd < 0) {
        perror("Error while accepting client connection");
        unlink(UNIX_SOCKET_PATH);
        close(sd);
        return 1;
    } else {
        readBytes = read(connection_fd, data, sizeof(data)-1);
        if (readBytes < 0) {
            perror("Error while reading from client");
        } else {
            data[readBytes] = '\0'; // 确保字符串结束
            printf("Data received from client is %s\n", data);
        }
        writeBytes = write(connection_fd, "Hi, I am the server!\n", 21);
        if (writeBytes < 0) {
            perror("Error while sending data to client");
        } else {
            printf("Data sent to client successfully\n");
        }
    }

    close(connection_fd);
    close(sd);
    unlink(UNIX_SOCKET_PATH); // 正常退出时清理文件
    return 0;
}

修改后的客户端代码

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/un.h>
#include <string.h>

#define UNIX_SOCKET_PATH "/tmp/unix_socket"

int main()
{
    int sd;
    int connection_status;

    struct sockaddr_un server;
    
    int readBytes, writeBytes;
    char data[200];

    sd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (sd < 0) {
        perror("Error while creating a socket");
        return 1;
    }

    printf("Client socket successfully created!!\n");

    // 初始化UNIX域套接字地址结构体
    server.sun_family = AF_UNIX;
    strncpy(server.sun_path, UNIX_SOCKET_PATH, sizeof(server.sun_path) - 1);

    connection_status = connect(sd, (struct sockaddr *)&server, sizeof(server));
    printf("Connection status: %d\n", connection_status);

    if (connection_status < 0) {
        perror("Error while connecting with server");
        close(sd);
        return 1;
    }
    printf("Client successfully connected to server\n");

    writeBytes = write(sd, "Hi, I am a client\n", 18);
    if (writeBytes < 0) {
        perror("Error while writing to the server");
    } else {
        printf("Data sent to the server!\n");
    }

    readBytes = read(sd, data, sizeof(data)-1);
    if (readBytes < 0) {
        perror("Error while reading data from server");
    } else {
        data[readBytes] = '\0'; // 确保字符串结束
        printf("The data from server is %s\n", data);
    }

    close(sd);
    return 0;
}

内容的提问来源于stack exchange,提问作者kakarot-757

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 10:41:18