当客户端尝试连接到服务器时,如果客户端和服务器都是localhost,则可能发生自连接(源端口和目标端口碰巧是相同的。)。但我的问题是,客户端没有收听该端口,如何实现自连接?
答案 0 :(得分: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! */ }
答案 1 :(得分:1)
localhost中的服务器和客户端不使用相同的端口。
作为连接的Tcp连接,
对于服务器,源端口为A,目标端口为B.
对于客户端,源端口为B,目标端口为A.
A由服务器中的bind()设置,并且对所有clinets都是已知的; B通常由clinets的内核分配,并且在服务器的accept()返回时为服务器所知。
详情:
在tcp中,服务器的端口由bind()设置,它允许我们指定端口号,IP地址,两者或两者都没有,但TCP服务器很少让内核选择短暂的端口。之后, server listen()端口和IP地址。
和客户端使用connect(),其套接字地址结构必须包含服务器的IP地址和端口号。 如有必要,内核将同时选择短暂的端口和源IP地址。无论如何,它不能是服务器使用的端口。
也就是说,服务器的端口和同一台计算机中的clinet是不一样的。
例如,当在本地主机中运行的简单C / S程序,在终端中键入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
prots明显不同。
如果强制客户端使用同一个服务器端口使用本地by bind(),则bind()将返回-1作为错误。
答案 2 :(得分: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