C++ 如何获取用于connect()的getaddrinfo()接口(addrinfo)的IP

C++ 如何获取用于connect()的getaddrinfo()接口(addrinfo)的IP,c++,windows,networking,ip,winsock2,C++,Windows,Networking,Ip,Winsock2,我需要能够验证我的应用程序是否使用了正确的接口,我认为最好的方法是知道它试图使用的接口的IP struct addrinfo *result = NULL, *ptr = NULL, hints; getaddrinfo(sServer.c_str(),默认_端口,提示和结果) 在前三次测试中,我得到了44.x.x.x,200.x.x,

我需要能够验证我的应用程序是否使用了正确的接口,我认为最好的方法是知道它试图使用的接口的IP

struct addrinfo                 *result = NULL,
                                *ptr = NULL,
                                hints;
getaddrinfo(sServer.c_str(),默认_端口,提示和结果)


在前三次测试中,我得到了
44.x.x.x
200.x.x
60.x.x
IP,所以有些地方不太对劲。我可以验证当它是一个有效的套接字时,我是否能够在
localhost

之间发送/接收连接后,调用
getsockname()
以查找套接字本地端的地址(
getpeername
用于远程端)


您还可以在
connect()
之前调用
bind()
,以选择特定的本地地址。。。如果您想让操作系统像根本不调用bind时那样选择一个空闲临时端口,请将零作为端口号传递。

连接后,调用
getsockname()
以查找套接字本地端的地址(
getpeername
用于远程端)

您还可以在
connect()
之前调用
bind()
,以选择特定的本地地址。。。如果您想让操作系统像根本不调用bind时那样选择一个空闲临时端口,请将零作为端口号传递。

这就成功了:

SOCKADDR_IN ClientSocketInterface;
memset(&ClientSocketInterface, 0, sizeof(ClientSocketInterface));
int iNlen = sizeof(ClientSocketInterface);

getsockname(m_ConnectSocket, (SOCKADDR*)&ClientSocketInterface, &iNlen);

string sIP = inet_ntoa(ClientSocketInterface.sin_addr);
STrace = String::Format("Client IP: [{0}:{1}]", gcnew String(sIP.c_str()), htons(ClientSocketInterface.sin_port));
Trace(STrace, TRACE_INFO);
这就成功了:

SOCKADDR_IN ClientSocketInterface;
memset(&ClientSocketInterface, 0, sizeof(ClientSocketInterface));
int iNlen = sizeof(ClientSocketInterface);

getsockname(m_ConnectSocket, (SOCKADDR*)&ClientSocketInterface, &iNlen);

string sIP = inet_ntoa(ClientSocketInterface.sin_addr);
STrace = String::Format("Client IP: [{0}:{1}]", gcnew String(sIP.c_str()), htons(ClientSocketInterface.sin_port));
Trace(STrace, TRACE_INFO);

使用
getsockname()
的示例也会有帮助。使用
getsockname()
的示例也会有帮助。您的
getsockname()
的最后一个参数是错误的。您需要将
sizeof()
值赋给一个实
int
变量,然后将指向该变量的指针传递给
getsockname()
(它可以修改该值,因此它必须是实变量),不要简单地将
sizeof()
值直接键入到指针。您也没有对
getsockname()
的返回值进行任何错误处理。不要调用
inet\u ntoa()
如果
getsockname()
失败,数据将成为垃圾。此外,在调用
getaddrinfo()
时,您没有显示填充
提示
变量的值。如果它返回一个IPv6地址,并且您创建了一个IPv6套接字,那么在
变量中使用
sockaddr\u将不起作用,您需要使用
sockaddr\u in6
或更好的
sockaddr\u存储
。而
inet\u ntoa()
仅适用于IPv4,而不适用于IPv6,因此您需要使用
inet\u ntop()
或等效物。此外,
getaddrinfo()
可以为给定主机返回多个IP地址,因此您应该在整个
addrinfo
链中循环。如果一个地址失败,请尝试下一个地址,依此类推,直到一个地址成功或链耗尽。如果需要,请再次重试整个链,并根据需要重复。您显示的
while
循环不考虑
addrinfo
链中的多个IP地址。如果要将代码限制为IPv4,请确保在
提示中指定
AF\u INET
,而不是
AF\u INET6
AF\u unsec
。阅读:“对于
ai_系列
,值
AF_unsec
表示调用者将接受任何协议系列。此值可用于返回
pNodeName
参数所指向主机名的IPv4和IPv6地址,因此您必须注意传递给
socket()的实际
ai_系列
,它可能是
AF_INET
AF_INET6
,这会影响该套接字上
sockaddr\u XXX
结构的所有使用。您的
getsockname()
的最后一个参数错误。您需要分配
sizeof()
将值转换为实
int
变量,然后将指向该变量的指针传递给
getsockname()
(这可以修改值,因此它需要是实变量),不要简单地将
sizeof()
值直接转换为指针。而且您没有对
getsockname()执行任何错误处理
的返回值。不要调用
inet\u ntoa()
如果
getsockname()
失败,数据将是垃圾数据。此外,调用
getaddrinfo()时,您没有显示填充
提示的
变量的值
。如果它返回一个IPv6地址,而您创建了一个IPv6套接字,那么在
变量中使用
sockaddr\u将不起作用,您需要在6
中使用
sockaddr\u或更好的
sockaddr\u存储
。而
inet\u ntoa()
仅在IPv4中起作用,而不是在IPv6中,因此您需要使用
inet\u ntop()
或同等标准。此外,
getaddrinfo()
可以为给定的主机返回多个IP地址,因此您应该在整个
addrinfo
链中循环。如果一个地址失败,请尝试下一个地址,依此类推,直到一个地址成功或链耗尽。如果需要,请再次重试整个链,并根据需要重复。您显示的
while
循环不会出现错误在
addrinfo
链中计算多个IP地址。如果要将代码限制为IPv4,请确保在
提示中指定
AF\u INET
,而不是
AF\u INET6
AF\u unsec
。阅读:
ai_系列
AF_unsec
值表示调用者将接受任何协议系列。此值可用于返回
pNodeName
参数所指向主机名的IPv4和IPv6地址,因此您必须注意传递给
socket()的实际
ai_系列
,它可以是
AF\u INET
AF\u INET6
,这会影响该套接字上
sockaddr\u XXX
结构的所有使用。
SOCKADDR_IN ClientSocketInterface;
memset(&ClientSocketInterface, 0, sizeof(ClientSocketInterface));
int iNlen = sizeof(ClientSocketInterface);

getsockname(m_ConnectSocket, (SOCKADDR*)&ClientSocketInterface, &iNlen);

string sIP = inet_ntoa(ClientSocketInterface.sin_addr);
STrace = String::Format("Client IP: [{0}:{1}]", gcnew String(sIP.c_str()), htons(ClientSocketInterface.sin_port));
Trace(STrace, TRACE_INFO);