【问题标题】:Messages not sending across networks (Python - sockets)不通过网络发送的消息(Python - 套接字)
【发布时间】:2015-09-06 10:48:54
【问题描述】:

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

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

【问题讨论】:

  • 不在同一个子网上会有什么问题?
  • @stark 我已将回溯添加到帖子中

标签: python sockets networking


【解决方案1】:

更新

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

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


原答案

是什么让您认为它在不同网络上的客户端之间不起作用?您是否能够测试来自不同网络的连接?

网络之间的路由消息通常不在应用层代码中完成,它是通过网络设备(例如路由器)的组合来执行的,这些设备在您的应用程序外部。

因为您的代码将套接字绑定到主机名'',所以您的应用程序正在侦听它正在运行的主机上的所有可用接口。只要有从客户端到服务器的路由,它对客户端连接来自的服务器没有影响。

您问“额外的步骤是什么?”。就您的代码而言,不应该有任何代码。但是,您可能需要在客户端和/或服务器上配置路由表,打开防火墙端口以允许从/到客户端和服务器的双向流量,或配置路由器以引导网络之间的流量。有关如何执行此操作的详细信息超出了 SO 的范围。

【讨论】:

  • 好的,谢谢您的 cmets - 我是否需要服务器的公共 IP 地址才能在客户端之间创建路由?
  • 不,您只需要在客户端可以访问的主机上运行服务器。 “公共 IP 地址”通常被理解为全球可访问的 IP 地址,例如实时 Web 服务器使用的 IP 地址。因此,如果您在服务器上有其中之一,那么您应该能够从您的客户端连接到它 - 前提是本地客户端主机上存在通往公共互联网的路由。否则,在不了解您正在处理的网络基础架构的情况下很难为您提供建议。
  • 你可以用pingtracerttelnet等命令行工具来测试一下。你能用@建立从客户端机器到服务器的连接吗? 987654328@ 使用 IPself.mainprocess.port 的值?
  • 感谢您的提示,我会尽快进行测试!完成后我会在这里发表评论。
猜你喜欢
  • 2017-09-26
  • 1970-01-01
  • 2014-07-23
  • 2019-03-31
  • 1970-01-01
  • 2015-01-10
  • 2015-07-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多