Linux x86_64、gcc、ipv4。
以下是我了解如何找出我的 IPv4 客户端。首先,我从一个客户端句柄开始,它不是一个指针而是一个整数(嗯?)。然后,我需要为目标 sockaddr 结构分配空间,并为 unsigned int 分配空间以保存其长度(作为引用传递)。然后我用整数客户端句柄和我的目标 sockaddress 和 sockaddress 长度调用 getsockname()。 (在内部,大概 getsockname() 将内核的 IP 表示和其他信息复制到我自己的 sockaddr 中。)然后我需要使用 sockaddr 结构调用 ntoa() 来获取字符串。最后,我需要将这个字符串转换成一个整数。 (还有 getpeername 和 getsockname。)
这些是我见过的例子。对于延迟很重要的服务器来说,这似乎是可移植的但效率低下。但是假设我想留在 x86_64 架构和 IPv4 上的 linux 中。我猜想内核内部已经在某个地方存储了一个 IP 号码作为 int,所以这里的大多数往返调用都是不必要的,这样就可以直接查找 IPv4,并且无需中间存储就可以更快。这样的功能存在吗?找了半天也没找到。
如果 getsockname() 函数有一个仅将 IP 表示形式返回为单个整数的替代方法,那将很有意义。这也将节省制作副本的时间和开销。这存在吗? (PS:顺便说一下,如果它确实存在,那么有一个类似于 ntoa() 的调用将这个每个 IP 唯一的 int 映射到标准的 xx.xx.xx.xx 字符串是合乎逻辑的,即避免需要中间 sock 地址。)
如果不存在这样的函数,至少,我应该可以避免ntoa到字符串再到整数的转换。这意味着我必须知道 sockaddr 结构中的哪些(甚至是否)字节表示 IP,因此我可以将这些字节转换为 4 字节的 C 整数。我认为这是字节 2-6。对吧?
/我是
最佳答案
我正在尝试解析您的问题 - 我可能会弄错一些细节。
“客户端句柄,不是指针而是整数”
- 实际上是一个 file descriptor .
“为目标 sockaddr 结构分配空间,并为 unsigned int 分配空间以保存其长度”
- 是的,这些确实需要分配,但从哪里分配并不重要。从堆栈分配肯定比从堆分配更快(malloc() 和 friend )
“我用整数客户端句柄和我的目标 sockaddress 和 sockaddress 长度调用 getsockname()”
我不确定您是在寻找给定套接字的本地地址还是远程地址:
- getsockname()会给你本地地址。
- getpeername()会给你远程地址。
无论如何,如果您只需要 IP 地址的 int
表示 - struct sockaddr_in
,我认为不需要任何类似 ntoa() 的调用由 get[peer|sock]name() 调用填写的内容已经包含在 sin_addr
member 中.
因此,假设您已经拥有客户端 FD(从 accept()
返回)并且您想要该套接字的远程地址,那么您需要做的就是像这样:
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
...
struct sockaddr_in peer_sa; // Stack allocation
socklen_t peer_sa_len = sizeof(struct sockaddr_in); // Stack allocation
int fd;
int status;
...
// fd is the client file descriptor, as returned by accept()
status = getpeername(fd, (struct sockaddr *)&peer_sa, &peer_sa_len);
// check your return codes!
printf("peer address %s as int is %d\n",
inet_ntoa(peer_sa.sin_addr), peer_sa.sin_addr.s_addr);
注意 inet_ntoa(peer_sa.sin_addr)
仅用于说明目的。
另请注意,这是非常 IPv4 特定的。如果您也希望使用 IPv6 客户端,那么您需要改用 struct sockaddr_storage
(它的大小应该足够大以适应任何地址族)。此外,128 位 IPv6 地址显然不适合 32 位整数。您还必须使用 inet_ntop()给出地址的文本表示。
关于c - 在 linux x86_64 下非常快速地 ip-as-int 查找 IPv4 套接字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19370805/