C++ 如何获取用于connect()的getaddrinfo()接口(addrinfo)的IP
我需要能够验证我的应用程序是否使用了正确的接口,我认为最好的方法是知道它试图使用的接口的IPC++ 如何获取用于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,
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);