Windows客户端可否指定ephemeral端口实现无数据传输通信
问题解答
结论
Windows系统下的客户端完全可以手动指定临时(ephemeral)端口,你提供的适配代码已经完成了该功能的验证。
实现逻辑
这种不发送业务数据的隐式传信方案,核心是利用TCP连接中客户端源端口可自定义的特性:客户端在调用connect()和服务端建立连接前,先通过bind()函数主动给客户端套接字绑定指定的端口,替代系统自动分配的临时端口,服务端接受连接时读取客户端源端口即可解析出预定义的信息。比如示例中指定客户端端口为7273,对应ASCII码就是HI,按顺序使用端口7279、8732、6582、6932、8979、8563发起连接,就能传递信息HOW ARE YOU?。
核心代码示例
服务端读取客户端端口代码
// Accept a client socket struct sockaddr_in client_addr; socklen_t slen = sizeof(client_addr); ClientSocket = accept(ListenSocket, (struct sockaddr*)&client_addr, &slen); printf("SECRET: %u\n", ntohs(client_addr.sin_port));
适配后的Windows客户端代码
#define WIN32_LEAN_AND_MEAN #include <windows.h> #include <winsock2.h> #include <ws2tcpip.h> #include <stdlib.h> #include <stdio.h> // Need to link with Ws2_32.lib, Mswsock.lib, and Advapi32.lib #pragma comment (lib, "Ws2_32.lib") #pragma comment (lib, "Mswsock.lib") #pragma comment (lib, "AdvApi32.lib") #pragma warning(disable : 4996) int __cdecl main(int argc, char** argv) { WSADATA wsaData; SOCKET ConnectSocket = INVALID_SOCKET; // Initialize Winsock WSAStartup(MAKEWORD(2, 2), &wsaData); // Two buffer are for message communication char buffer1[256], buffer2[256]; struct sockaddr_in my_addr, my_addr1; int client = socket(AF_INET, SOCK_STREAM, 0); if (client < 0) printf("Error in client creating\n"); else printf("Client Created\n"); my_addr.sin_family = AF_INET; my_addr.sin_addr.s_addr = INADDR_ANY; my_addr.sin_port = htons(27015); // This ip address will change according to the machine my_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // Explicitly assigning port number 7273 by // binding client with that port my_addr1.sin_family = AF_INET; my_addr1.sin_addr.s_addr = INADDR_ANY; my_addr1.sin_port = htons(7273); // This ip address will change according to the machine my_addr1.sin_addr.s_addr = inet_addr("127.0.0.1"); if (bind(client, (struct sockaddr*)&my_addr1, sizeof(struct sockaddr_in)) == 0) printf("Binded Correctly\n"); else printf("Unable to bind\n"); socklen_t addr_size = sizeof my_addr; int con = connect(client, (struct sockaddr*)&my_addr, sizeof my_addr); if (con == 0) printf("Client Connected\n"); else printf("Error in Connection\n"); return 0; }
运行效果


使用注意事项
- 手动指定的端口不能被本地其他进程占用,否则会绑定失败
- 端口号只要在0-65535范围内未被占用即可使用,不受Windows默认临时端口范围(49152-65535)限制
- 如果要连续使用不同端口发起多个连接,每个连接需要新建独立的套接字重新绑定,已绑定过的套接字无法重复绑定其他端口(开启SO_REUSEADDR选项的特殊场景除外)
内容的提问来源于stack exchange,提问作者vengy
相关产品推荐
相关产品推荐

