2

当客户端尝试连接服务器时,如果客户端和服务器都是localhost,则可能会发生自连接(源端口和目标端口恰好相同。)。但我的问题是,客户端没有监听该端口,如何实现自连接?

4

3 回答 3

2

我在遇到同样的现象后发现了你的问题。我找到的最好的解释是在Everything About Nothing: TCP Client Self Connect

您可以通过 getsockname() 请求分配给您的端口并将其与远程端口进行比较以检测这些自连接:

sockaddr_in addr_client;
socklet_t len = sizeof(saddr_in);

if(getsockname(sock_client, (struct sockaddr *)&addr_client, &len))
    { /* error */ }
if(len != sizeof(saddr_in)))
    { /* error */ }

if(addr_client.sin_port == addr_server.sin_port &&
  addr_client.sin_addr.s_addr == addr_server.addr.sin_addr.s_addr)
    { /* self-connection detected! */ }
于 2017-09-25T15:18:49.550 回答
1

localhost 中的服务器和客户端不使用相同的端口。

作为已连接的 Tcp 连接,

对服务器来说,源端口是A,目的端口是B。

对于客户端,源端口是B,目的端口是A。

A 由服务器中的 bind() 设置,所有客户端都知道;B 通常由客户端的内核分配,并且在服务器的 accept() 返回时为服务器所知。

详细说明:

在 tcp 中,服务器的端口由 bind() 设置,它允许我们指定端口号、IP 地址,或者两者都不指定,但是 TCP 服务器很少让内核选择一个临时端口。 ) 端口和 IP 地址。

客户端使用connect(),其套接字地址结构必须包含服务器的IP地址和端口号。 如有必要,内核将同时选择一个临时端口和源 IP 地址。无论如何,它不能是您的服务器使用的端口。

也就是说,同一台计算机上的服务器和客户端的端口是不一样的。

例如,当简单的 C/S 程序在 localhost 中运行时,在终端中键入 netstat -t,您将得到:

Proto Recv-Q Send-Q Local Address           Foreign Address             State      
tcp        0      0 localhost:41742         localhost:9877          ESTABLISHED
tcp        0      0 localhost:9877          localhost:41742         ESTABLISHED

优点明显不同。

如果您通过 bind() 强制客户端使用与本地服务器相同的端口,则 bind() 将返回 -1 作为错误。

于 2013-05-27T09:08:48.453 回答
0

我们可以用下面的python程序简单的重现这个现象

import socket
for i in range(65536):
  try:
    s = socket.create_connection(('127.0.0.1', 50000))
    print 'connected to {0}'.format(s.getpeername())
  except Exception as e:
    pass

当我们尝试连接同一主机中的某个套接字时。如果我们不将您的客户端绑定到特定端口,操作系统将为ephemeral port您提供。如果它恰好是您想要连接的那个。它会导致自我连接。确保您尝试连接的端口位于/proc/sys/net/ipv4/ip_local_port_range

于 2015-05-31T15:08:03.003 回答