TCP客户端异常自连接问题求助:重启后连接自身而非服务器
问题原因与代码修正
核心错误原因
1. 错误绑定客户端Socket并连接自身
你手动调用bind将客户端Socket绑定到127.0.0.1:50000,紧接着又用同一个地址结构调用connect:
- 当服务端未运行时,Windows本地的
50000端口空闲,bind会成功,此时connect会直接连接到客户端自己,形成自连接,这就是Wireshark中看到的现象。 - 首次启动时WSL2的服务端占用了自身网络栈的
50000端口,但Windows与WSL2的网络栈是隔离的,Windows本地的50000端口不受影响,所以客户端bind成功后,你以为连接到了WSL2的服务端,实际代码逻辑本质错误。
2. 混淆客户端本地地址与服务端目标地址
connect的参数应该是服务端的IP和端口,你却复用了客户端绑定的地址结构,导致目标地址完全错误。
3. 未初始化Winsock库
Windows下使用Winsock API(如socket、connect)必须先调用WSAStartup初始化库,否则函数行为会异常,甚至返回不可预期的错误。
4. 错误的错误码获取方式
Windows下Winsock的错误码需要用WSAGetLastError()获取,而非标准C的errno。
修正后的客户端代码
#include <iostream> #include <winsock2.h> #include <ws2tcpip.h> #pragma comment(lib, "ws2_32.lib") #define BUF_SIZE 29 // 替换为WSL2虚拟机的实际IP(在WSL2中执行ip addr show eth0查看inet字段) const char* SERVER_IP = "192.168.1.x"; const int SERVER_PORT = 50000; int main() { // 初始化Winsock库 WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { std::cerr << "WSAStartup失败,错误码:" << WSAGetLastError() << std::endl; return -1; } // 创建TCP Socket SOCKET client_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (client_sock == INVALID_SOCKET) { std::cerr << "创建Socket失败,错误码:" << WSAGetLastError() << std::endl; WSACleanup(); return -1; } // 配置服务端地址 sockaddr_in server_addr{}; server_addr.sin_family = AF_INET; inet_pton(AF_INET, SERVER_IP, &server_addr.sin_addr); server_addr.sin_port = htons(SERVER_PORT); // 连接服务端 if (connect(client_sock, (sockaddr*)&server_addr, sizeof(server_addr)) == SOCKET_ERROR) { std::cerr << "连接服务端失败,错误码:" << WSAGetLastError() << std::endl; closesocket(client_sock); WSACleanup(); return -1; } std::cout << "已连接到服务端" << std::endl; // 发送数据 char data[BUF_SIZE] = "-199.5;-299.5;-399.5;-499.5;"; data[BUF_SIZE - 1] = '\0'; for (int k = 0; k <= 10; k++) { int send_len = send(client_sock, data, BUF_SIZE, 0); if (send_len == SOCKET_ERROR) { std::cerr << "发送数据失败,错误码:" << WSAGetLastError() << std::endl; break; } std::cout << "已发送:" << data << std::endl; } // 清理资源 closesocket(client_sock); WSACleanup(); return 0; }
关键注意事项
- WSL2网络隔离:Windows的
127.0.0.1和WSL2的127.0.0.1不属于同一网络栈,必须用WSL2虚拟机的实际IP连接服务端; - 客户端无需手动绑定:正常场景下,客户端Socket不需要调用
bind,系统会自动分配临时端口和本地IP; - 错误检查:所有Winsock API调用后都要检查返回值,及时定位问题;
- 资源清理:程序结束前必须关闭Socket并调用
WSACleanup释放资源。
内容的提问来源于stack exchange,提问作者Nadran
相关产品推荐
相关产品推荐

