2015-09-06 58 views
0

我正在实现一个简单的聊天应用程序,您可以在客户端之间发送消息。它工作正常,如果客户端在同一个网络上,但我想知道如何让它工作,如果客户端不在同一个网络上。需要额外的步骤是什么?邮件不通过网络发送(Python - 套接字)

我提供了我下面的代码,它适用于同一网络通信。 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

当它们不在同一个子网上时它有什么问题? – stark

+0

@stark我已经加入了回溯到后 – petehallw

回答

0

更新

您已经添加了一个回溯到你的问题这表明远程网络不可达。在这种情况下,您的代码充当客户端,因此我的原始答案并不直接解决您的问题,但是,一般原则是相同的,即远程主机无法联系,因为没有到达网络的路由主持人在听。

我认为你需要看看你的本地网络配置,以解决 - 这不是你的代码有问题。您可能需要设置一个路由到远程网络......我不是Windows的家伙,但您可以查看route命令,可能this answer可能会有所帮助。


原来的答复

是什么让你认为它没有客户端之间不同的网络上工作?你是否能够测试来自不同网络的连接?网络之间

路由消息通常不会在应用层代码完成,它是与网络设备,诸如路由器,其是外部应用程序的组合来执行。

因为你的代码绑定套接字主机'',您的应用程序正在监听其所运行的主机上的所有可用接口。对于客户端连接来自的服务器,只要存在从客户端到服务器的路由,就没有区别。

你问“有什么额外的步骤?”。就你的代码而言,不应该有任何代码。但是,您可能需要在客户端和/或服务器上配置路由表,打开防火墙端口以允许来往/来自客户端和服务器的双向流量,或配置路由器以引导网络之间的流量。如何做到这一点的细节超出了SO的范围。

+0

好的,谢谢你的意见 - 不要升需要,以创造客户之间的路由服务器公网IP地址? – petehallw

+0

不,您只需要在客户端可访问的主机上运行服务器。 “公共IP地址”通常被理解为指全球可访问的IP地址,例如实时Web服务器使用的IP地址。因此,如果您的服务器上有其中一个服务器,那么您应该能够从客户端连接到它 - 假设到本地客户端主机上的公用Internet的路径已经就位。否则,很难在不知道正在处理的网络基础结构的情况下通知您。 – mhawke

+0

你可以使用'ping','tracert','telnet'等命令行工具来测试一些东西。你是否能够通过telnet建立从客户机到服务器的连接, IP'和'self.mainprocess.port'? – mhawke