我正在尝试编写一些与IP无关的代码,根据各种来源的建议,我尝试使用sockaddr_storage。然而,所有的API调用(getaddrinfo、getnameinfo)仍然依赖于struct sockaddr。并且它们之间进行转换并不是一个好的选择,会引起很多其他问题。
将其分别转换为sockaddr_in和sockaddr_in6也有点违背了我使用sockaddr_storage的初衷。
有没有人能够有效地在开发简单的客户端服务器套接字应用程序中使用sockaddr_storage。
if (addr.ss_family == AF_INET)
sendto(sock, buffer, len, 0, (sockaddr*)&addr, sizeof(sockaddr_in))
else (addr.ss_family == AF_INET6)
sendto(sock, buffer, len, 0, (sockaddr*)&addr, sizeof(sockaddr_in6));
然后,这种“if family == AF_INET”的表达式很容易重复出现。这是你想要避免的。
假设您正在使用C++,您会发现一个用于套接字地址对象的抽象类非常有用。我在github上有一个示例这里和这里。CSocketAddress类由{sockaddr、sockaddr_in、sockaddr_in6}的联合支持,并且可以使用sockaddr_storage构造。如果我在开始编写此类之前就知道了sockaddr_storage,我将使用它来代替联合。无论如何,它使我能够编写以下代码:
CSocketAddress addr;
...
sendto(sock, buffer, len, 0, addr.GetSockAddr(), addr.GetSockAddrLength());
sockaddr_storage addrstorage = {};
int len = sizeof(sockaddr_storage);
accept(sock, (sockaddr*)&addrstorage, &len);
CSocketAdddress addr(addrstorage); // construct an address object to pass around everywhere else
struct sockaddr_storage
,它的作用是为任何给定协议的sockaddr结构分配足够的空间,但在IP版本无关的代码中,你有多少次需要这样做?通常情况下,您调用getaddrinfo()
,然后它会给您一堆struct sockaddr *
,您不关心它们是否是sockaddr_in
还是sockaddr_in6
,只需将它们原样传递到bind()
和connect()
(无需转换)。struct sockaddr_storage
有用的主要地方是为accept()
的第二个参数保留空间。在这种情况下,我同意必须将其强制转换为struct sockaddr *
两次,一次用于accept()
,另一次用于getnameinfo()
。但我看不出有避免这些转换的方法。这是C,结构继承总是涉及到很多转换。
gethostbyname()
的另一个原因。应该使用getaddrinfo()
代替。 - Celada