我正在开发一个服务器并且作为参数传递的 ip 不起作用
I'm developing a server and ip passed as parameter not working
我正在使用:
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()
的 return 值 分配给您的 sockaddr
变量,而不是分配 in_addr
结构inet_aton()
输出。 return 值不是 IP 地址!
inet_aton()
returns 成功时为非零值,失败时为 0。也就是说,它的return值基本上是一个布尔值
使用 IP 地址 0.0.0.0
(又名 INADDR_ANY
)调用 bind()
指示它将 AF_INET
套接字绑定到指定端口上的所有本地网络接口,这对于服务器来说是很常见的(并且通常是首选的)。
调用 inet_aton("localhost")
失败 因为您不能将主机名传递给 inet_aton()
,所以它 returns 0,然后你 bind()
使用 sockaddr_in
的套接字,其 s_addr
设置为 INADDR_ANY
,没问题,所以你的代码 似乎 与 "localhost"
一起工作,但只是侥幸。
调用inet_aton("127.0.0.1")
或inet_aton("192.168.30.1")
成功,所以returns非零,然后您 bind()
使用 sockaddr_in
的套接字,其 s_addr
设置为无效 IP,导致 bind()
彻底失败,或者更糟的是绑定到现有网络与您期望的不同的界面。
此外,inet_aton()
输出的 in_addr
已经是网络字节顺序,因此无需在其输出上调用 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"
等
我正在使用:
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()
的 return 值 分配给您的 sockaddr
变量,而不是分配 in_addr
结构inet_aton()
输出。 return 值不是 IP 地址!
inet_aton()
returns 成功时为非零值,失败时为 0。也就是说,它的return值基本上是一个布尔值
使用 IP 地址 0.0.0.0
(又名 INADDR_ANY
)调用 bind()
指示它将 AF_INET
套接字绑定到指定端口上的所有本地网络接口,这对于服务器来说是很常见的(并且通常是首选的)。
调用 inet_aton("localhost")
失败 因为您不能将主机名传递给 inet_aton()
,所以它 returns 0,然后你 bind()
使用 sockaddr_in
的套接字,其 s_addr
设置为 INADDR_ANY
,没问题,所以你的代码 似乎 与 "localhost"
一起工作,但只是侥幸。
调用inet_aton("127.0.0.1")
或inet_aton("192.168.30.1")
成功,所以returns非零,然后您 bind()
使用 sockaddr_in
的套接字,其 s_addr
设置为无效 IP,导致 bind()
彻底失败,或者更糟的是绑定到现有网络与您期望的不同的界面。
此外,inet_aton()
输出的 in_addr
已经是网络字节顺序,因此无需在其输出上调用 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"
等