【问题标题】:How to use a Python 3 socket client/server setup over the internet (not locally)?如何通过互联网(不是本地)使用 Python 3 套接字客户端/服务器设置?
【发布时间】:2026-01-12 10:55:01
【问题描述】:

我正在尝试实现一个简单的聊天程序,该程序使用套接字通过 UDP 连接传输数据。但是,我不知道如何正确设置它,以便如果我将它托管在我的笔记本电脑上,我本地网络之外的人可以访问它。我正在使用端口 5000,并在我的路由器上为我的笔记本电脑转发了该端口。端口转发似乎不是问题。至少来自 portforward.com 的“端口转发网络实用程序”似乎检测到它已正确转发。也许我混淆了我需要托管和连接的 IP 地址?有问题的代码如下:

import socket
import threading
import sys


class Server:
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    connections = []

    def __init__(self):
        self.sock.bind(('192.168.1.5', 5000))
        self.sock.listen(1)

    def handler(self, c, a):
        while True:
            data = c.recv(1024)
            for connection in self.connections:
                print(data.decode())
                connection.send(data)
            if not data:
                break

    def run(self):
        while True:
            c, a = self.sock.accept()
            cThread = threading.Thread(target=self.handler, args=(c, a))
            cThread.daemon = True
            cThread.start()
            self.connections.append(c)
            print(self.connections)


class Client:
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    usr_name = ""

    def sendMsg(self):
        while True:
            self.sock.send(bytes(self.usr_name + ": " + input("-> "), 'utf-8'))

    def __init__(self, address):
        self.sock.connect((address, 5000))
        self.usr_name = input("Enter a username: ")
        iThread = threading.Thread(target=self.sendMsg)
        iThread.daemon = True
        iThread.start()

        while True:
            data = self.sock.recv(1024)
            if not data:
                break
            print(data.decode())


if len(sys.argv) > 1:
    client = Client(sys.argv[1])
else:
    server = Server()
    server.run()

如您所见,我输入了当前的本地 IP 地址来托管服务器,而客户端则要求连接到 IP。我不知道现在该怎么做才能通过互联网托管它,但我已经尝试了我能想到的所有 IP 组合,但它返回了许多错误。

提前致谢。

编辑: 我得到的两个主要错误是:

  • 超时错误 [WinError 10060]
    • 我的朋友在尝试从其他网络连接时收到此消息
  • [WinError 10061]
    • 我在尝试使用同一台计算机上的公共 IP 进行连接时会收到此信息

很抱歉,我无法更详细地说明我的错误并提供完整的打印输出,如果我能够复制它们,我会尝试更新。

编辑: 我能够重写它并让它工作,我不再需要这方面的帮助。 谢谢。

【问题讨论】:

  • 你必须给客户端你的路由器的公共IP地址。那是您尝试过的IP之一吗?此外,服务器的 LAN 地址应该没问题,但 0.0.0.0 也应该没问题,它更简单、可移植、不太可能打错等。'
  • 同时,“许多错误”不是任何人都可以调试的。如果您没有准确告诉我们您从哪个组合中得到了哪些错误(或者,更重要的是,为我们提供合理组合的完整错误回溯,但您可能直到现在才知道),我们无法调试它。
  • 最后一件事:您确定您将 UDP 5000 转发到 5000,而不是 TCP 5000 转发到 5000,或 UDP 5000 转发到某个任意端口或其他任何端口吗?

标签: python sockets network-programming


【解决方案1】:

您正在将 UDP 端口 5000 端口转发到 5000。

但是您打开的是 TCP 流,而不是 UDP。这就是SOCK_STREAM 的意思。如果你想要UDP,你需要使用SOCK_DGRAM

因此,您需要使这两者保持一致。唯一的问题是,我不确定你真正想要的是哪一个。

一方面,您的代码正在执行面向连接的recv,并且似乎假设可靠传输,这意味着您可能需要TCP。

另一方面,您的代码似乎假设每个recv(1024) 将从另一侧得到一个send,这仅适用于UDP; TCP sockets are byte streams, not message streams。当您执行recv(1024) 时,您可以轻松获得80 字节行的前12 个字节,这意味着它可以在UTF-8 字符的中间结束,这意味着decode 将引发异常。

我认为您需要 TCP,但在其上具有帧协议。在这里可能有意义的最简单的协议是文本行。这很容易由您自己完成,但使用 socket.makefile 更容易完成,因为您为每个连接指定了一个线程。

【讨论】:

  • 好的,谢谢您的回答,这对您有很大帮助。我试图给出上面的错误,但我手头没有完整的回溯,我可能需要一段时间来复制错误才能得到它们。我对网络编程非常陌生(您可能会说),但非常感谢您的帮助。我现在将尝试实施您在上面列出的更改,并且可能会坚持使用 UDP。
  • @DesperateConcept 你一定有一些理由认为你想要 UDP 而不是 TCP。我只是想猜测这里有什么意义;你应该知道你实际上想要做什么。
  • 好的,我可能会尝试使用您提供的一些技巧重写代码。看起来我的问题可能集中在 TCP 与 UDP 以及我如何处理套接字而不是我最初认为的 IP 上。再次感谢。
最近更新 更多