如何在 2 台 PC 之间的 Python 中创建 TCP 连接
How can I create a TCP connection in Python between 2 PCs
到目前为止,我已经制作了一个非常基本的 client/server 应用程序来创建 TCP 连接。我有很多编程经验,只是从来没有做过这种低级的东西,尤其是在网络方面。请注意,所有打印件都只是为了帮助我弄清楚发生了什么。一个已知的问题是 jsonip 有时会给我一个 IPv4,有时会给我一个 v6,我不知道为什么,但现在这并不重要,只是为了警告任何想要重新创建我的代码的人。
服务器:
import socket
import requests
port = int(input("Enter port you want to open:\n"))
#todo: add errorhandling
print("Adding socket...")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
hostname = socket.gethostname()
print(f"Hostname: {hostname}")
ip_address = socket.gethostbyname(hostname)
print(f"Host address: {ip_address}")
r = requests.get(r'http://jsonip.com')
public_ip_address = r.json()['ip']
s.bind((ip_address, port))
print("Is open for connections on IP: "+public_ip_address+" and Port: "+str(port))
s.listen(5)
print("Done initialisation, listening for incoming connections...")
while True:
clientsocket, address = s.accept()
print(f"Connection from {address} has been established")
clientsocket.send(bytes(f"You have connected to server: {hostname}", "utf-8"))
客户:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ip = input("Enter IP to connect to:\n")
port = int(input("Enter Port to connect to:\n"))
print(f"Connecting to server {ip} ...")
s.connect((ip, port))
msg = s.recv(1024)
print(msg.decode("utf-8"))
在我的本地机器上:在我的 server.py 中打开 20000,它告诉我主机是 127.0.1.1,然后我在我的客户端脚本中输入 127.0.1.1 和 20000,然后它们连接。所以Socket已经和127.0.1.1绑定了。 (附带问题:这个 IP 地址是什么,它是否像我 PC 中进程的内部 IP 地址之类的?如果 运行 ip a
在我的另一台机器上,它是 2 中显示的第一个)
在我的机器上使用 Virtmanager 和 运行 一个 Linux 服务器(仅限命令行)和一个正常的 Ubuntu,服务器再次告诉我主机是 127.0.1.1我不需要进入另一个 VM 就知道它不会工作,但是有效的是通过 ip a
获取服务器的 IP 地址,在本例中为 192.168.122.37,当我将此 IP 地址输入客户端时,它会连接。但是在这里的套接字中,我再次绑定了 127.0.1.1,所以我放在这里是任意的吗?我应该在这里绑定什么,public,奇怪的还是 192. 地址?
我无法开始工作的第一件事是使用 2 个物理设备。在我的 Linux 机器上打开服务器时,我根本无法连接到我的 windows 机器,无论我使用我的 public、我的 127. 还是我的 192. IP 地址。现在我的最终目标是通过互联网进行此操作,所以我自己走上去,在这里描述了我尝试到达我想去的地方所采取的步骤,但在这里我碰壁了,我不知道哪里出了问题。我是不是在服务器上绑定了错误的地址,我的路由器有问题,还有什么问题吗?
我也试过使用我朋友的电脑离开我的网络几个国家,但这也只是导致超时(我的理论是他试图打开的路由器端口已关闭,我现在知道我如何可以让路由器向他的 PC 发送数据,这应该不是不可能的,因为 firefox 和每个使用互联网的应用程序都可以做到这一点,而无需我手动转发每个端口,我只是不知道如何)。这是我的最终目标,在我的朋友电脑和我的电脑之间建立连接,这就是我的进展(如果它与解决全球连接问题无关,我不介意跳过本地网络),所以,tl;博士:我做错了什么,我需要绑定什么,我需要做什么才能使最终结果生效?
有很多问题要回答。
地址 127.X.X.X 为环回接口保留,最常见的是 127.0.0.1。 loopback 是一个虚拟但重要的接口,正如您可能已经猜到的那样,它只能在本地计算机上使用。 您不能使用 127.X.X.X 地址使两台主机相互通信。
地址 192.168.X.X(以及 10.X.X.X 和 172.16-31.X.X。)为本地 LAN 保留。它们在 Internet 上无效。
您不能使用这些地址使两台主机通过 public Internet 相互通信(除非您创建隧道,这是一个高级网络主题)
几乎每个人都使用它们,因为我们 运行 很久以前就没有 IPv4 地址了,它们很难获得,价格昂贵等等。而且这些主机与 Internet 隔离,只能通过以下方式访问它们t运行 指定地址的路由器。这种路由器功能称为 NAT。典型的路由器有一个有效的 Internet 地址,所有到 Internet 的连接都显示为来自该路由器。 如果您通过 PC 连接 jsonip.com
之类的服务,您将获得路由器的地址,而不是 PC 的地址。
另请参阅:Finding local IP addresses using Python's stdlib
要使您的程序运行,请使其接受所有接口上的连接。请参阅 socket docs 中的第一个示例。在 Linux 上,使用 >= 1024 的端口号。小于 1024 的端口已保留,普通用户无法使用。
最后一点是防火墙可能会阻止与您的服务器的连接。这取决于您的系统和设置。
到目前为止,我已经制作了一个非常基本的 client/server 应用程序来创建 TCP 连接。我有很多编程经验,只是从来没有做过这种低级的东西,尤其是在网络方面。请注意,所有打印件都只是为了帮助我弄清楚发生了什么。一个已知的问题是 jsonip 有时会给我一个 IPv4,有时会给我一个 v6,我不知道为什么,但现在这并不重要,只是为了警告任何想要重新创建我的代码的人。
服务器:
import socket
import requests
port = int(input("Enter port you want to open:\n"))
#todo: add errorhandling
print("Adding socket...")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
hostname = socket.gethostname()
print(f"Hostname: {hostname}")
ip_address = socket.gethostbyname(hostname)
print(f"Host address: {ip_address}")
r = requests.get(r'http://jsonip.com')
public_ip_address = r.json()['ip']
s.bind((ip_address, port))
print("Is open for connections on IP: "+public_ip_address+" and Port: "+str(port))
s.listen(5)
print("Done initialisation, listening for incoming connections...")
while True:
clientsocket, address = s.accept()
print(f"Connection from {address} has been established")
clientsocket.send(bytes(f"You have connected to server: {hostname}", "utf-8"))
客户:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ip = input("Enter IP to connect to:\n")
port = int(input("Enter Port to connect to:\n"))
print(f"Connecting to server {ip} ...")
s.connect((ip, port))
msg = s.recv(1024)
print(msg.decode("utf-8"))
在我的本地机器上:在我的 server.py 中打开 20000,它告诉我主机是 127.0.1.1,然后我在我的客户端脚本中输入 127.0.1.1 和 20000,然后它们连接。所以Socket已经和127.0.1.1绑定了。 (附带问题:这个 IP 地址是什么,它是否像我 PC 中进程的内部 IP 地址之类的?如果 运行 ip a
在我的另一台机器上,它是 2 中显示的第一个)
在我的机器上使用 Virtmanager 和 运行 一个 Linux 服务器(仅限命令行)和一个正常的 Ubuntu,服务器再次告诉我主机是 127.0.1.1我不需要进入另一个 VM 就知道它不会工作,但是有效的是通过 ip a
获取服务器的 IP 地址,在本例中为 192.168.122.37,当我将此 IP 地址输入客户端时,它会连接。但是在这里的套接字中,我再次绑定了 127.0.1.1,所以我放在这里是任意的吗?我应该在这里绑定什么,public,奇怪的还是 192. 地址?
我无法开始工作的第一件事是使用 2 个物理设备。在我的 Linux 机器上打开服务器时,我根本无法连接到我的 windows 机器,无论我使用我的 public、我的 127. 还是我的 192. IP 地址。现在我的最终目标是通过互联网进行此操作,所以我自己走上去,在这里描述了我尝试到达我想去的地方所采取的步骤,但在这里我碰壁了,我不知道哪里出了问题。我是不是在服务器上绑定了错误的地址,我的路由器有问题,还有什么问题吗?
我也试过使用我朋友的电脑离开我的网络几个国家,但这也只是导致超时(我的理论是他试图打开的路由器端口已关闭,我现在知道我如何可以让路由器向他的 PC 发送数据,这应该不是不可能的,因为 firefox 和每个使用互联网的应用程序都可以做到这一点,而无需我手动转发每个端口,我只是不知道如何)。这是我的最终目标,在我的朋友电脑和我的电脑之间建立连接,这就是我的进展(如果它与解决全球连接问题无关,我不介意跳过本地网络),所以,tl;博士:我做错了什么,我需要绑定什么,我需要做什么才能使最终结果生效?
有很多问题要回答。
地址 127.X.X.X 为环回接口保留,最常见的是 127.0.0.1。 loopback 是一个虚拟但重要的接口,正如您可能已经猜到的那样,它只能在本地计算机上使用。 您不能使用 127.X.X.X 地址使两台主机相互通信。
地址 192.168.X.X(以及 10.X.X.X 和 172.16-31.X.X。)为本地 LAN 保留。它们在 Internet 上无效。
您不能使用这些地址使两台主机通过 public Internet 相互通信(除非您创建隧道,这是一个高级网络主题)
几乎每个人都使用它们,因为我们 运行 很久以前就没有 IPv4 地址了,它们很难获得,价格昂贵等等。而且这些主机与 Internet 隔离,只能通过以下方式访问它们t运行 指定地址的路由器。这种路由器功能称为 NAT。典型的路由器有一个有效的 Internet 地址,所有到 Internet 的连接都显示为来自该路由器。 如果您通过 PC 连接 jsonip.com
之类的服务,您将获得路由器的地址,而不是 PC 的地址。
另请参阅:Finding local IP addresses using Python's stdlib
要使您的程序运行,请使其接受所有接口上的连接。请参阅 socket docs 中的第一个示例。在 Linux 上,使用 >= 1024 的端口号。小于 1024 的端口已保留,普通用户无法使用。
最后一点是防火墙可能会阻止与您的服务器的连接。这取决于您的系统和设置。