我正在编写一个玩具集合点/中继服务器,它在端口5555上侦听两个客户端“ A”和“ B”。
它的工作原理是:即使A和B不知道各自的IP,服务器从第一个连接的客户端A接收到的每个字节也会发送到第二个连接的客户端B, >:
~/.bashrc
此代码当前有效:
~/.bash_profile
,您可以通过在服务器上启动它进行测试,并对其进行两个netcat连接: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
。
然后我如何将信息传递给客户端A和B,使他们可以直接相互通信,而无需通过服务器传输字节?
有2种情况:
一般情况,即即使A和B不在同一个本地网络中
在这两个客户端位于同一本地网络(例如:使用同一家庭路由器)的特殊情况下,当这两个客户端将通过端口5555连接到服务器时,这将显示在服务器上:>
# 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
备注:此处先前未成功的尝试:UDP or TCP hole punching to connect two peers (each one behind a router) 和UDP hole punching with a third party
答案 0 :(得分:1)
接受的答案给出了解决方案。在“客户端A和客户端B在同一个本地网络中” 的情况下,这是一些其他信息。 如果服务器注意到两个客户端具有相同的公共IP,则确实可以检测到这种情况。
然后服务器可以选择客户端A作为“本地服务器”,选择客户端B作为“本地客户端”。
然后,服务器将向客户端A询问其“本地网络IP”。 Client A can find it with:
import socket
localip = socket.gethostbyname(socket.gethostname()) # example: 192.168.1.21
,然后将其发送回服务器。服务器将将此“本地网络IP”传达给客户端B。
然后,客户端A将运行“本地服务器”:
import socket
soc = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
soc.bind(('0.0.0.0', 4000))
data, client = soc.recvfrom(1024)
print("Connected client:", client)
print("Received message:", data)
soc.sendto(b"I am the server", client)
并且客户端B将作为“本地客户端”运行:
import socket
soc = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server = ('192.168.1.21', 4000) # this "local network IP" has been sent Client A => server => Client B
soc.sendto("I am the client", server)
data, client = soc.recvfrom(1024)
print("Received message:", data)