TCP套接字中的IP地址

时间:2011-07-08 12:32:21

标签: sockets tcp network-programming ip-address

我有一个根节点(服务器)通过TCP套接字连接到许多其他节点(客户端)。我想从服务器向客户端发送一些数据,但每个节点的数据不同,取决于该节点的IP地址。

因此我应该拥有连接到服务器的每个节点的IP地址。我怎么能得到这些信息?

3 个答案:

答案 0 :(得分:2)

当您致电accept(2)时,您可以选择检索客户的地址。

int accept(int socket, struct sockaddr *restrict address,
    socklen_t *restrict address_len);

您需要存储这些地址,然后将send(2)存储到您需要发送的每个地址。​​

所以工作流程应该是这样的:

  • 保留已连接客户端的列表。最初列表是空的,当然
  • 当您接受连接时,将其详细信息推送到该列表(accept(2)返回的地址和套接字)。
  • 当您需要向每个客户发送内容时,只需走一下列表并发送(使用存储的套接字)

一个棘手的部分是socklen_t *restrict address_len是一个值 - 结果参数,所以你需要小心。

答案 1 :(得分:2)

这是一个比第一次出现的更细微的问题。

如果客户端位于NAT后面,您可能会从多个客户端获得相同的IP。这是完全自然和预期的行为。如果您需要区分同一NAT后面的多个客户端,您将需要一些其他形式的唯一客户端ID(例如,IP地址端口)。

答案 2 :(得分:1)

只要您可以访问连接的TCP套接字的文件描述符列表,就可以轻松检索远程主机的地址。关键是getpeername()系统调用,它允许您查找套接字远程端的地址。示例C代码:

// This is ugly, but simpler than the alternative
union {
    struct sockaddr sa;
    struct sockaddr_in sa4;
    struct sockaddr_storage sas;
} address;
socklen_t size = sizeof(address);

// Assume the file descriptor is in the var 'fd':
if (getpeername(fd, &address.sa, &size) < 0) {
    // Deal with error here...
}

if (address.sa.family == AF_INET) {
    // IP address now in address.sa4.sin_addr, port in address.sa4.sin_port
} else {
    // Some other kind of socket...
}