c - 在 linux x86_64 下非常快速地 ip-as-int 查找 IPv4 套接字?

标签 c linux sockets tcp

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。对吧?

/我是

最佳答案

我正在尝试解析您的问题 - 我可能会弄错一些细节。

客户端句柄,不是指针而是整数

为目标 sockaddr 结构分配空间,并为 unsigned int 分配空间以保存其长度

  • 是的,这些确实需要分配,但从哪里分配并不重要。从堆栈分配肯定比从堆分配更快(malloc() 和 friend )

我用整数客户端句柄和我的目标 sockaddress 和 sockaddress 长度调用 getsockname()

我不确定您是在寻找给定套接字的本地地址还是远程地址:

无论如何,如果您只需要 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/

相关文章:

file - C 错误 : expected expression before ‘FILE’

linux - 如何仅删除文件所有行中的前两个前导空格

linux - Linux 中 PID_MAX 取决于什么因素

javascript - 带有 JavaScript TCP 客户端的浏览器

c# - 使用GPRS的WM6 socket

c - 指向数组的指针的表示是什么?

c++ - 如果 C/C++ 中的字符串没有 NUL 字符(以防编译器允许它通过),会发生什么情况?

Java 套接字 - 为什么我需要 PrintWriter 来完成这项工作?

c - 重新分配无效的下一个大小

linux - sed 删除 # 和 # 之间的字符并添加 :'s in bash script?