【发布时间】:2019-04-28 00:18:35
【问题描述】:
我正在为两个客户端“A”和“B”编写一个在端口 5555 上侦听的玩具会合点/中继服务器。
它的工作原理是这样的:服务器从第一个连接的客户端 A 收到的每个字节都会发送到第二个连接的客户端 B,即使 A 和 B 不知道各自的 IP:
A -----------> server <----------- B # they both connect the server first
A --"hello"--> server # A sends a message to server
server --"hello"--> B # the server sends the message to B
此代码目前正在运行:
# server.py
import socket, time
from threading import Thread
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.bind(('', 5555))
socket.listen(5)
buf = ''
i = 0
def handler(client, i):
global buf
print 'Hello!', client, i
if i == 0: # client A, who sends data to server
while True:
req = client.recv(1000)
buf = str(req).strip() # removes end of line
print 'Received from Client A: %s' % buf
elif i == 1: # client B, who receives data sent to server by client A
while True:
if buf != '':
client.send(buf)
buf = ''
time.sleep(0.1)
while True: # very simple concurrency: accept new clients and create a Thread for each one
client, address = socket.accept()
print "{} connected".format(address)
Thread(target=handler, args=(client, i)).start()
i += 1
您可以通过在服务器上启动它来测试它,并对其进行两次 netcat 连接:nc <SERVER_IP> 5555。
我怎样才能将信息传递给客户端 A 和 B,使他们可以直接相互通信,而不需要通过服务器传输字节?
有两种情况:
一般情况,即即使 A 和 B 不在同一个本地网络中
-
这两个客户端在同一个本地网络中的特殊情况(例如:使用同一个家庭路由器),当两个客户端将连接到服务器上的端口 5555 时,这将显示在服务器上:
('203.0.113.0', 50340) connected # client A, router translated port to 50340 ('203.0.113.0', 52750) connected # same public IP, client B, router translated port to 52750
备注:之前在这里尝试不成功:UDP or TCP hole punching to connect two peers (each one behind a router) 和UDP hole punching with a third party
【问题讨论】:
-
同一网络上的主机直接通过二层局域网地址进行通信。除非数据包发往不同的网络,否则这些帧不会通过路由器。查看this question的答案。
-
@RonMaupin 举个简单的例子:在同一个家用路由器上通过 WiFi 连接的两台笔记本电脑需要路由器相互传递数据,对吧? 如果我的脚本(请参阅问题)检测到相同的公共 IP 上有哪些信息,应该将哪些信息传递给它们每个人?
-
没有。家用路由器实际上是一个科学怪人盒子。你所说的是一个路由器/防火墙/交换机/WAP,都在一个盒子里。 Wi-Fi 上的帧是桥接的,它们从不通过盒子里的路由器,只通过 WAP。路由器在不同网络之间路由第 3 层数据包。网桥(WAP 和交换机也是网桥)将桥接同一网络上的第 2 层帧。
-
如果服务器注意到两个客户端使用相同的公共IP,服务器可以传递什么样的信息,以允许客户端A和B之间的直接连接?那么它们应该如何相互连接呢?客户端 A 不必知道客户端 B 的本地 IP,反之亦然。软件SyncThing 的工作原理是这样的:两个客户端可以见面,如果他们相距很远,可以交换数据。如果它们在同一个本地网络中,则在它们之间直接建立连接(仅家庭路由器)!它非常好用,您无需提供 IP,它会自动检测到它。
-
如果您将服务器配置为网络基础设施设备,那么您需要配置一个网桥来桥接同一网络上的帧,否则,您需要配置一个路由器来在不同网络之间路由数据包。
标签: python sockets networking nat hole-punching