python - 如何通过互联网(不是本地)使用 Python 3 套接字客户端/服务器设置?

标签 python sockets network-programming

我正在尝试实现一个简单的聊天程序,该程序使用套接字通过 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]
  • 我的 friend 在尝试从另一个网络连接时收到此消息
  • [WinError 10061]
  • 当我尝试使用来自同一台计算机的公共(public) IP 进行连接时,我会收到此消息

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

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

    最佳答案

    您正在将 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,但在其之上有一个帧协议(protocol)。在这里可能有意义的最简单的协议(protocol)是文本行。这很容易自己完成,但使用 socket.makefile 更容易完成,假设您为每个连接指定一个线程。

    关于python - 如何通过互联网(不是本地)使用 Python 3 套接字客户端/服务器设置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50710118/

    相关文章:

    Java如何等待命令完成?

    c++ - 通过套接字发送 HBITMAP

    python - 在python中生成随机值列表,其中每个值出现一定的百分比

    Python tkinter Canvas 动态创建.Line

    java - 具有循环消息传递的简单客户端服务器

    java - 允许应用程序使用网络发送或接收数据?

    bash - crontab 和手动运行脚本之间的不同结果

    c - 超时阻塞函数调用,没有线程,没有外部库

    python - Unicode解码错误: position of the error

    用于距离聚类的 Python 库