我正在编写一个inetd 的克隆,我必须在其中运行一个服务器来打印连接到它的客户端的IP 和端口。
当我覆盖STDIN
并STDOUT
使用套接字描述符时,我最初的解决方案是恢复sockaddr_in
包含所需信息的结构。然而,这样做getsockname()
会返回一个空结构,所有位都设置为 0。
知道我的方法有什么问题吗?我可以使用其他方法来恢复 IP/端口吗?
谢谢
正如 R.. 指出的那样,您应该使用getpeername
. 该函数都将getsockname
文件描述符作为其第一个参数,而不是流指针 ( FILE *
)。用于fileno(stdin)
获取标准输入的文件描述符(或将其硬编码为STDIN_FILENO
,因为它是常量)。
此外,getsockname
and的最后一个参数getpeername
应该是指向 的指针socklen_t
,而不是常量,您应该将 asockaddr_in
用于 TCP/IP:
struct sockaddr_in peeraddr;
socklen_t peeraddrlen = sizeof(peeraddr);
getpeername(STDIN_FILENO, &peeraddr, &peeraddrlen);
在此处查看完整示例。
使用getpeername
. 我怀疑您的问题是getsockname
返回您自己的(本地)套接字端的信息,这可能绑定到 0.0.0.0 (这意味着它可以接受来自任何接口的连接)。
编辑:我想我在阅读代码时发现了你的实际错误。这一行是错误的:
getsockname(stdin, &addr, sizeof(addr));
getsockname
andgetpeername
函数将( socklen_t *
a pointer ) 作为第三个参数,而不是 a size_t
。编译器应该会告诉你这个错误,除非你忘记在getsockname
. 此外,正如已经说过的,stdin
是不正确的。尝试:
socklen_t len = sizeof addr;
getpeername(0, &addr, &len);
或(仅限 C99):
getpeername(0, &addr, (socklen_t[1]){sizeof addr});
您还应该检查返回值;如果你这样做了,你会看到它返回错误。
如果您需要远程客户端的这些信息,则必须调用getpeername()。