(如何)从套接字文件描述符确定套接字族

7

我正在编写一个API,其中包括IPC函数,用于向另一个进程发送数据,该进程可以是本地的或者在另一台主机上。我希望发送函数尽可能简单:

int mySendFunc(myDataThing_t* thing, int sd);

在mySendFunc()函数的调用上下文中,不需要调用者知道sd是指本地进程还是远程进程。如果我能做到以下操作:

switch (socketFamily(sd)) {
case AF_UNIX:
case AF_LOCAL:
   // Send without byteswapping
   break;
default:
   // Use htons() and htonl() on multi-byte values
   break;
}

建议我实现socketFamily()的方式如下:

socketFamily()的实现方法如下:

unsigned short socketFamily(int sd)
{
   struct sockaddr sa;
   size_t len;
   getsockname(sd, &sa, &len);   
   return sa.sa_family;
}

但是我有点担心getsockname()的效率,我想知道每次发送时是否负担得起。


我注意到了你的最后一个问题,我已经编辑了我的帖子。 - Eduard - Gabriel Munteanu
3个回答

6
请参阅 getsockname(2)。然后检查 struct sockaddr 的族群。
编辑:另外,有时查询 info 也很有用,比如这个例子中的 info libc sockets
编辑:
你不能在不查找的情况下知道它。它无法简单缓存,因为套接字号可以通过关闭和重新打开来重复使用。我刚刚查看了glibc代码,似乎getsockname只是一个系统调用,这可能会影响性能。
但我的建议是使用某种面向对象的概念。让用户将之前由您返回的结构体指针传递给他,即通过您的API注册/打开套接字。然后,您可以缓存关于该套接字的任何内容。

我曾感到困惑,但后来我意识到你可以传递的每个不同结构体都有一个带有族信息的无符号短整型作为第一个元素。我的my_sockaddr.sa_family == AF_UNIX。 - xaxxon

2

为什么不总是使用网络字节顺序发送数据?


因为我经常会进行本地IPC,不想在每个多字节值上执行hton*()然后ntoh*()。 - Chris Nelson
为什么不呢?无论如何,在网络情况下,您都需要这段代码。在IPC的上下文中,有没有证据表明字节交换是瓶颈? - fizzer
@fizzer,跟Xorg团队说吧。没错,这很重要。 - Eduard - Gabriel Munteanu
每当进行网络通信时,如果您希望应用程序具有良好的可扩展性,尽可能地减少数据复制是非常重要的。 - 17 of 26
这里有一点需要注意。如果我们假设端点之间没有协作,我不确定应该采取什么措施:本地套接字通常是否期望数据以网络字节顺序传输? - Eduard - Gabriel Munteanu
我相信确实是这样的,是的。 - 17 of 26

1
如果您控制客户端和服务器代码,我有一个不同的建议,我过去曾经成功地使用过。
让消息的前四个字节成为已知的整数值。接收方可以检查前四个字节以查看它是否与已知值匹配。如果匹配,则无需进行字节交换。
这样可以避免在两台机器具有相同的字节序时进行字节交换。

除非我误解你的意思,那对接收来说是有效的,但对发送不起作用。 - Chris Nelson
使用这种技术,字节交换只在接收端进行。发送方从不进行交换 - 它只是在其余数据之前设置了那个4字节值。通过查看接收端的4个字节,接收方就知道是否需要交换。 - 17 of 26
这个的美妙之处在于只要发送方和接收方的字节序匹配,即使它们不在网络字节序中也不会进行字节交换。 - 17 of 26
是的,尽管如果有人决定单方面使用它,例如制作HTTP检索器,它就不起作用了。 - Eduard - Gabriel Munteanu
没错,这里的警告是你需要控制连接的两端。或者至少能够向另一方规定条款 :). 原帖作者的情况对我来说不太清楚。 - 17 of 26

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接