Linux / Unix Socket自连接

时间:2013-05-27 05:58:22

标签: linux sockets unix tcp unix-socket

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

3 个答案:

答案 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