UNIX Socket绑定失败:非套接字操作问题求助
UNIX Socket绑定/监听/连接报错:"socket operation on non-socket" 问题排查
问题现象
Socket初始化完成后,调用bind、listen、connect均返回-1,报错信息为socket operation on non-socket。已尝试设置SO_REUSEADDR和SO_REUSEPORT选项,问题未解决。
问题根源
1. Socket类成员变量未正确初始化
在Network::Socket构造函数中,创建socket时使用了局部变量sock,而非类的成员变量sock。这导致类的sock成员始终处于未初始化的垃圾值状态,后续调用get_sock()返回的不是有效的socket描述符,因此所有基于该无效描述符的socket操作都会触发"socket operation on non-socket"错误。
2. 缺少关键系统调用的错误检查
setsockopt调用后未检查返回值,若socket创建失败,后续操作仍会基于无效描述符执行,无法提前发现问题。
修复方案
修改Socket构造函数
将局部变量sock替换为类成员变量赋值,并增加setsockopt的错误检查:
#include "Socket.hpp" Network::Socket::Socket(int domain, int service, int protocol, int port, unsigned long interface) { // 初始化地址结构 address.sin_family = domain; address.sin_port = htons(port); address.sin_addr.s_addr = htonl(interface); // 创建socket,直接赋值给类成员变量sock sock = socket(domain, service, protocol); test_connection(sock); int reuse = 1; // 检查SO_REUSEADDR设置结果 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0) { perror("setsockopt SO_REUSEADDR failed"); exit(EXIT_FAILURE); } // 检查SO_REUSEPORT设置结果 if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (const char*)&reuse, sizeof(reuse)) < 0) { perror("setsockopt SO_REUSEPORT failed"); exit(EXIT_FAILURE); } std::cout << "Testing Socket" << std::endl; } // 测试连接的逻辑不变 void Network::Socket::test_connection(int to_test) { std::cout << "in test connection " << to_test << std::endl; if (to_test < 0) { perror("Connection failed"); exit(EXIT_FAILURE); } } // Getters不变 struct sockaddr_in Network::Socket::get_address() { return address; } int Network::Socket::get_sock() { return sock; }
修复TestServer中的字符串长度问题
responder函数中sizeof(hello_msg)获取的是指针大小,而非字符串实际长度,需替换为strlen:
void Network::TestServer::responder() { char *hello_msg = "Hello from server"; // 使用strlen获取字符串实际长度 write(new_socket, hello_msg, strlen(hello_msg)); close(new_socket); }
验证说明
修复后,get_sock()会返回有效的socket描述符,bind、listen、connect等操作将基于合法的socket执行,报错问题会被解决。同时新增的错误检查能提前排查setsockopt等调用的异常情况。
内容的提问来源于stack exchange,提问作者Evgenii Isaenko
相关产品推荐
相关产品推荐

