2

我以前见过这个问题,但我从来没有找到有效的答案。我需要获取我的服务器所连接的计算机的显式 IP 地址(即 123.456.789.100)和端口号,以便将该信息转发给其他客户端。我在 Windows 7(家庭高级版)、Visual Studio 2010 Professional 上使用 WinSock2.h - 制作“C++ 控制台应用程序”。这是一个 TCP 连接。到目前为止,这是我的代码:

sockaddr_in* addr = new sockaddr_in;
int addrsize = sizeof(addr);
getsockname(clientSock, (sockaddr*)addr, &addrsize);
char* ip = inet_ntoa(addr->sin_addr);
int port = addr->sin_port;
printf("IP: %s ... PORT:%d\n", ip, port);

这总是给我 205.205.205.205 的 IP 和 52685 的 PORT 每次。我尝试了替代方案,包括 gethostbyname,它可以工作,但我需要实际的 IP 本身。我也试过用getpeername() 代替getsockname(),但结果是一样的。我在路由器后面,但到目前为止我在同一台机器上同时使用服务器和客户端。

提前感谢您的任何帮助!

4

2 回答 2

4

getpeername() 是您要使用的函数。

我在您的代码中看到的一些错误:

1)您在堆上分配地址。不需要这样做,只需声明“sockaddr_in addr;” 而是在堆栈上,并将 &addr(而不是 addr)传递给您的 getpeername() 调用。

2) addrsize 被设置为指针的大小(例如 4 或 8),而不是实际 sockaddr_in 的大小,这意味着......

3) getsockname() 可能失败,但你不知道,因为

4)您没有检查 getsockname() 的返回值以查看是否有错误,这意味着

5) 您看到的结果只是向您显示了在调用 getsockname()/getpeername() 之前在 (*addr) 中的任何随机垃圾数据,因为调用失败而没有向 addr 结构写入任何内容。

6) 哦,还有一件事……请务必将您对 addr.sin_addr 的引用包含在 ntohl() 调用中,并将您对 addr.sin_port 的引用包含在 ntohs() 调用中,否则您会将它们放在 big-在 little-endian(读取:基于 Intel)的计算机上运行时的 endian 形式,这不是您想要的。

于 2011-07-11T00:16:56.930 回答
2

是的,你是对的,它抛出了一个错误,我还没有检查它。非常感谢,您的解决方案奏效了。对我有用的最终代码如下:

sockaddr_in addr;
int addrsize = sizeof(addr);
int result = getpeername(clientSock, (sockaddr*) &addr, &addrsize);
printf("Result = %d\n", result);
char* ip = inet_ntoa(addr.sin_addr);
int port = addr.sin_port;
printf("IP: %s ... PORT: %d\n", ip, port);

这让我得到了正确的结果。我感谢您的帮助。谢谢!

于 2011-07-11T08:13:00.900 回答