如何通过Winsock查找服务名称与端口?求SERVENT结构替代方案
替代SERVENT结构查找服务名称与端口号的方案
SERVENT结构及配套的getservbyname()、getservbyport()函数已被标记为废弃,推荐使用以下现代API实现服务名称与端口号的互查:
一、根据服务名称查询端口号:使用getaddrinfo()
getaddrinfo()是跨平台的标准API,可根据服务名称(如"http"、"ssh")解析对应的端口号,同时支持IPv4和IPv6。
示例代码:
#include <winsock2.h> #include <ws2tcpip.h> #pragma comment(lib, "ws2_32.lib") int main() { WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); struct addrinfo hints = {0}, *result; hints.ai_family = AF_UNSPEC; // 兼容IPv4/IPv6 hints.ai_socktype = SOCK_STREAM; // 指定TCP类型服务 // 查找"http"服务对应的端口 int ret = getaddrinfo(NULL, "http", &hints, &result); if (ret == 0) { // 提取端口号(需转换为主机字节序) if (result->ai_family == AF_INET) { struct sockaddr_in* ipv4_addr = (struct sockaddr_in*)result->ai_addr; u_short port = ntohs(ipv4_addr->sin_port); printf("http服务端口:%d\n", port); } else if (result->ai_family == AF_INET6) { struct sockaddr_in6* ipv6_addr = (struct sockaddr_in6*)result->ai_addr; u_short port = ntohs(ipv6_addr->sin6_port); printf("http服务端口:%d\n", port); } freeaddrinfo(result); // 释放内存 } WSACleanup(); return 0; }
二、根据端口号查询服务名称:使用getnameinfo()
getnameinfo()可从套接字地址结构中反向解析出对应的服务名称,同样支持跨平台。
示例代码:
#include <winsock2.h> #include <ws2tcpip.h> #pragma comment(lib, "ws2_32.lib") int main() { WSADATA wsaData; WSAStartup(MAKEWORD(2, 2), &wsaData); struct sockaddr_in ipv4_addr = {0}; ipv4_addr.sin_family = AF_INET; ipv4_addr.sin_port = htons(80); // 指定要查询的端口(网络字节序) inet_pton(AF_INET, "127.0.0.1", &ipv4_addr.sin_addr); // 任意合法IP即可 char serv_name[NI_MAXSERV]; // 解析端口对应的服务名称 int ret = getnameinfo((struct sockaddr*)&ipv4_addr, sizeof(ipv4_addr), NULL, 0, serv_name, NI_MAXSERV, NI_NUMERICSERV); if (ret == 0) { printf("端口80对应的服务:%s\n", serv_name); } WSACleanup(); return 0; }
三、可选方案:直接解析系统services文件
Windows系统中,服务与端口的映射关系存储在C:\Windows\System32\drivers\etc\services文件中,你可以自行读取并解析该文件获取映射。但这种方式需要处理文件IO、格式解析,且无法实时获取系统动态更新的服务信息,仅作为API方案的补充。
内容的提问来源于stack exchange,提问作者DEV JUNGLE
相关产品推荐
相关产品推荐

