重启服务器遇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
相关产品推荐
相关产品推荐

