我正在实施一个简单的聊天应用程序,您可以在客户端之间发送消息。如果客户端在同一网络上,它可以正常工作,但我想知道如果客户端不在同一网络上,如何使其工作。需要额外的步骤是什么?
我在下面提供了我的代码,适用于同一网络通信。 serve()
在其自己的线程中运行并侦听传入的消息(通过调用rcvMsg()
)。当用户想要从mainprocess
发送消息时,它会调用sendMsg()
。
class CMsgGateway(QtCore.QThread):
def __init__(self, mainprocess, parent = None):
QtCore.QThread.__init__(self, parent)
self.exiting = False
self.mainprocess= mainprocess
self.msgRcvd = ""
serveThread = Thread(target=self.serve).start()
def serve(self):
while 1:
self.sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.bind(("", self.mainprocess.port))
self.sock.listen(1)
self.rcvMsg()
def rcvMsg(self):
serverSocket, info = self.sock.accept()
while 1:
try:
buf = bytearray(4000)
view = memoryview(buf)
bytes = serverSocket.recv_into(view, 4000)
if bytes:
stx = view[0]
Size = view[1:3]
bSize = Size.tobytes()
nTuple = struct.unpack(">H", bSize)
nSize = nTuple[0]
message = view[0:3+nSize]
messageString = message.tobytes().decode("utf-8").strip()
self.mainprocess.msgs += "Friend: " + messageString
self.emit(Qt.SIGNAL("msgRcvd"))
else:
break
except socket.timeout:
print("Socket timeout.")
sys.stdout.flush()
break
def messageReceived(self):
self.mainprocess.slotMsgRcvd(self.msgRcvd)
def sendMsg(self, msgToSend, IP):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 2)
self.sock.connect((IP, self.mainprocess.port))
self.sock.send(msgToSend.encode())
self.sock.close()
尝试交叉网络时收到的错误是:
Traceback (most recent call last):
File "chatApp.pyw", line 74, in slotMsgSend
File "C:\Users\me\documents\chatApp\source\msginterface.pyw", line 61, in sendMsg
self.sock.connect((IP, self.mainprocess.port))
OSError: [WinError 10051] A socket operation was attempted to an unreachable network
答案 0 :(得分:0)
<强>更新强>
您已在问题中添加了回溯,表明远程网络无法访问。在这种情况下,您的代码充当客户端,因此我的原始答案并不直接解决您的问题,但是,一般原则是相同的,即无法联系远程主机,因为没有到达网络的路由主持人在听。
我认为您需要查看本地网络配置才能解决问题 - 您的代码不会出现问题。您可能需要设置到远程网络的路由...我不是Windows用户,但您可以查看route
命令,可能this answer可能有帮助。
原始回答
是什么让您认为它在不同网络上的客户端之间不起作用?您是否能够测试来自不同网络的连接?
网络之间的路由消息通常不在应用程序层代码中完成,而是使用应用程序外部的网络设备(如路由器)的组合来执行。
因为您的代码将套接字绑定到主机名''
,所以您的应用程序正在侦听运行它的主机上的所有可用接口。如果存在从客户端到服务器的路由,则与客户端连接所在的服务器没有区别。
你问&#34;有什么额外的步骤?&#34;。就你的代码而言,不应该是任何代码。但是,您可能需要在客户端和/或服务器上配置路由表,打开防火墙端口以允许来自/到客户端和服务器的双向流量,或配置路由器以引导网络之间的流量。有关如何做到这一点的详细信息超出了SO的范围。