问题描述
在 VS2022 中使用 Winsock 编程时,如果代码中包含 inet_addr("127.0.0.1") 这样的语句,编译器会报错。
解决方案(方案一:使用 inet_pton)
inet_pton 能够同时处理 IPv4 和 IPv6 地址,并能检测无效 IP 格式。
步骤
- 包含必要的头文件
在源文件中添加#include <ws2tcpip.h>(放在#include <winsock2.h>之后)。 - 替换函数调用
将原来的addrSer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");替换为:
inet_pton(AF_INET, "127.0.0.1", &(addrSer.sin_addr));
- (可选)添加错误处理
inet_pton成功时返回 1,失败返回 0 或 -1。可以加上判断:
if (inet_pton(AF_INET, "127.0.0.1", &(addrSer.sin_addr)) != 1) {
// 处理错误(例如 IP 格式无效)
printf("IP 地址转换失败\n");
}
完整代码示例(TCP 客户端)
// tcpclient.cpp
#include <iostream>
#include <winsock2.h>
#include <ws2tcpip.h> // 添加此头文件
#pragma comment(lib, "ws2_32.lib")
int main() {
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
std::cout << "Winsock 初始化失败";
return 0;
}
SOCKET sockCli = socket(AF_INET, SOCK_STREAM, 0);
if (sockCli == INVALID_SOCKET) {
std::cout << "创建套接字失败";
WSACleanup();
return 0;
}
SOCKADDR_IN addrSer;
addrSer.sin_family = AF_INET;
addrSer.sin_port = htons(6000);
// 替换 inet_addr 为 inet_pton
if (inet_pton(AF_INET, "127.0.0.1", &(addrSer.sin_addr)) != 1) {
std::cout << "IP 地址格式错误";
closesocket(sockCli);
WSACleanup();
return 0;
}
if (connect(sockCli, (SOCKADDR*)&addrSer, sizeof(addrSer)) == SOCKET_ERROR) {
std::cout << "连接服务器失败";
closesocket(sockCli);
WSACleanup();
return 0;
}
std::cout << "连接服务器成功\n";
char sendbuf[256], recvbuf[256];
while (true) {
std::cout << "客户端说:";
std::cin >> sendbuf;
if (strcmp(sendbuf, "exit") == 0) break;
send(sockCli, sendbuf, strlen(sendbuf) + 1, 0);
int bytes = recv(sockCli, recvbuf, sizeof(recvbuf), 0);
if (bytes == SOCKET_ERROR) {
std::cout << "接收数据失败";
break;
}
recvbuf[bytes] = '\0'; // 确保字符串结尾
std::cout << "服务器说:" << recvbuf << std::endl;
}
closesocket(sockCli);
WSACleanup();
return 0;
}
TCP 服务器端对应的修改
需要修改 bind 之前的地址转换部分:
// 原代码(弃用)
addrSer.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // 绑定所有本地地址
// 使用 inet_pton 绑定指定 IP(如 "127.0.0.1"):
inet_pton(AF_INET, "127.0.0.1", &(addrSer.sin_addr));
// 绑定任意地址可使用宏 INADDR_ANY,但注意该宏不是字符串,不能直接用 inet_pton,可以保留原赋值方式(不警告)
addrSer.sin_addr.s_addr = htonl(INADDR_ANY); // 不会触发警告
其他注意事项
- IPv6 支持:若需要支持 IPv6,只需将
AF_INET改为AF_INET6,并确保地址字符串为 IPv6 格式。 - 错误检测:始终检查
inet_pton的返回值,避免无效 IP 导致后续错误。
inet_pton(AF_INET, “127.0.0.1”, &addr.sin_addr);// 把字符串”127.0.0.1″转换成二进制,存入addr.sin_addr
点分十进制转二进制格式
好高级
吹
好高级
竟然还有目录