首页 > 解决方案 > 如何在 Python 中创建两台 PC 之间的 TCP 连接

问题描述

到目前为止,我已经制作了一个非常基本的客户端/服务器应用程序来创建 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 地址ip a,在本例中为 192.168.122.37,当我将此 IP 地址输入客户端时,它会连接。但是在这里的套接字中,我再次绑定了 127.0.1.1,所以我放在这里是任意的吗?我应该在这里绑定什么,公众、怪人还是 192. 地址?

我无法上班的第一件事是使用 2 个物理设备。在我的 Linux 机器上打开服务器时,我根本无法连接到我的 windows 机器,无论我使用我的公共 IP 地址、我的 127. 还是我的 192. IP 地址。现在我的最终目标是在互联网上做这件事,所以我自己走,在这里描述我为尝试到达我想去的地方所采取的步骤,但在这里我碰到了一堵砖墙,我不知道哪里出了问题。我在服务器上绑定了错误的地址,是我的路由器有问题,还有其他问题吗?

我还尝试使用我的朋友电脑离开我的网络几个国家,但这也只会导致超时(我的理论是他试图打开的路由器端口已关闭,我现在知道如何让路由器发送数据到他的 PC,这应该不是不可能的,因为 firefox 和每个使用互联网的应用程序都不需要我手动转发每个端口,我只是不知道如何)。这是我的最终目标,在我的朋友 PC 和我的 PC 之间建立连接,这就是我能走多远(如果本地网络与解决全局连接问题无关,我不介意跳过本地网络),所以,tl;博士:我做错了什么,我需要绑定什么以及我需要做什么才能使最终结果起作用?

标签: pythonlinuxsocketstcpnetwork-programming

解决方案


有很多问题要回答。

地址 127.XXX 是为环回接口保留的,最常见的是 127.0.0.1。loopback 是一个虚拟的但重要的接口,正如您可能已经猜到的那样,它只能在本地机器上使用。您不能使用 127.XXX 地址使两台主机相互通信。


地址 192.168.XX(以及 10.XXX 和 172.16-31.XX)是为本地 LAN 保留的。它们在 Internet 上无效。

您不能使用这些地址使两台主机通过公共 Internet 相互通信(除非您创建隧道,这是一个高级网络主题)

几乎每个人都在使用它们,因为我们很久以前就用完了 IPv4 地址,它们很难获得,价格昂贵等。而且这些主机与 Internet 隔离,只能通过转换地址的路由器访问它们。这种路由器功能称为 NAT。典型的路由器有一个有效的 Internet 地址,所有到 Internet 的连接都显示为来自路由器。如果您jsonip.com使用 PC 等服务,您将获得路由器的地址,而不是 PC 的地址。

另请参阅:使用 Python 的 stdlib 查找本地 IP 地址


要使您的程序正常工作,请使其接受所有接口上的连接。请参阅套接字文档中的第一个示例。在 Linux 上,使用 >= 1024 的端口号。< 1024 的端口是保留的,普通用户不能使用。


最后一点是防火墙可能会阻止与您的服务器的连接。这取决于您的系统和设置。


推荐阅读