c++ - 我正在开发一个服务器,并且作为参数传递的 ip 不起作用
问题描述
我在用着:
struct in_addr ip;
#define HOST_PORT atoi(argv[2])
#define HOST_IP inet_aton(argv[1], &ip)
sockaddr_in sockaddr;
sockaddr.sin_family = AF_INET;
sockaddr.sin_addr.s_addr = htonl(HOST_IP);
sockaddr.sin_port = htons(HOST_PORT);
在cli中获取ip和端口号。然后我绑定、聆听、接受和阅读。
我进行编译,当我使用./server localhost 8080时,一切都按预期工作。
但是如果我使用./server 127.0.0.1 8080或./server 192.168.30.1 8080似乎是绑定和监听,没有错误,但我没有收到请求。
解决方案
你在滥用inet_aton()
.
您正在将返回值分配inet_aton()
给您的sockaddr
变量,而不是分配输出的in_addr
结构inet_aton()
。 返回值不是 IP 地址!
inet_aton()
成功返回非零值,失败返回 0。换句话说,它的返回值基本上是一个布尔值。
使用(aka )bind()
的 IP 地址调用指示它将套接字绑定到指定端口上的所有本地网络接口,这对于服务器来说是非常常见的(并且通常是首选)。0.0.0.0
INADDR_ANY
AF_INET
调用inet_aton("localhost")
失败,因为您无法将主机名传递给inet_aton()
,因此它返回0,然后您使用设置为的bind()
套接字,这没关系,因此您的代码似乎可以使用,但只是侥幸。sockaddr_in
s_addr
INADDR_ANY
"localhost"
调用inet_aton("127.0.0.1")
orinet_aton("192.168.30.1")
成功,因此它返回非零,然后您使用设置为无效 IP 的套接字,导致完全bind()
失败,或者更糟的是绑定到与您期望的不同的现有网络接口.sockaddr_in
s_addr
bind()
此外,in_addr
那个inet_aton()
输出已经是网络字节顺序,所以不需要调用htonl()
它的输出。
试试这个:
struct in_addr ip;
#define HOST_PORT atoi(argv[2])
#define HOST_IP ((inet_aton(argv[1], &ip) != 0) ? ip.s_addr : 0)
struct sockaddr_in sockaddr;
memset(&sockaddr, 0, sizeof(sockaddr));
sockaddr.sin_family = AF_INET;
sockaddr.sin_addr.s_addr = HOST_IP;
sockaddr.sin_port = htons(HOST_PORT);
// use sockaddr as needed ...
或者,干脆去掉你的HOST_IP
和HOST_PORT
宏,因为它们并没有真正帮助你:
struct sockaddr_in sockaddr;
memset(&sockaddr, 0, sizeof(sockaddr));
sockaddr.sin_family = AF_INET;
inet_aton(argv[1], &(sockaddr.sin_addr));
sockaddr.sin_port = htons(atoi(argv[2]));
// use sockaddr as needed ...
话虽这么说,你真的应该使用getaddrinfo()
,例如:
struct addrinfo hints, *res;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_PASSIVE;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
if (getaddrinfo(argv[1], argv[2], &hints, &res) == 0)
{
// use res->ai_addr and res->ai_addrlen with socket() and bind() as needed ...
freeaddrinfo(res);
}
getaddrinfo()
会将 IP 地址字符串和主机名字符串解析为适合sockaddr_...
您的结构,并愉快地处理与本地主机相关的字符串,如"localhost"
, "127.0.0.1"
,"192.168.30.1"
等。
推荐阅读
- html - 在 flexed div 的中间垂直对齐内容
- elasticsearch - Elasticsearch:使用过滤器和 constant_score 优化查询?
- javascript - 允许键入不在选项中的值
- python - 如何将dict的键值对打印为对齐表?
- python - 使用python反转给定数组并将其添加到给定数组
- java - 如何从 imageView 获取图像并将其存储到 Firebase 存储
- c# - 反序列化复杂 json 时获取 NULL 值
- kubernetes - 避免一个 k8s 主节点/etc 节点成为领导者
- android - 如何从 Uri 修剪视频,包括 `mp4parser` 库可以处理的文件,但使用 Android 的框架?
- sql - SQL - 返回不同的行,其中 1 列值用作不同的标识符