2015-09-06 57 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