如何让Python套接字对外可见?

2 投票
2 回答
4591 浏览
提问于 2025-04-16 00:24

我之前发过一个类似的问题,但我越来越沮丧,因为我的网络设置看起来没有问题。其他软件可以从外部访问(比如 netcat 监听的服务器等),但我的脚本却不行……这是怎么回事呢?

注意:在局域网内可以正常工作,但在互联网上不行。

服务器:

import socket

host = ''
port = 80001

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host,port))
s.listen(1)
print 'Listening..'
conn, addr = s.accept()
print 'is up and running.'
print addr, 'connected.'
s.close()
print 'shut down.'

客户端:

import socket
host = '80.xxx.xxx.xxx'
port = 80001

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
s.close()

有人能帮帮我吗?

非常感谢任何帮助。

Jake

2 个回答

9

再次编辑补充:

我觉得你可能对套接字通信的一些基础知识还不太了解。要让套接字正常工作,你需要确保客户端和服务器上的套接字能够相互连接。根据你最新的修改,你的服务器现在绑定到了63001端口,但它是在本地回环适配器上,也就是127.0.0.1。

计算机有多个网络适配器,至少有两个:一个是本地回环适配器,它可以让你快速地在同一台机器上进行网络连接(用于测试、进程间通信等),另一个是让你连接到实际网络的网络适配器。很多计算机可能还有更多的适配器(比如虚拟适配器、无线和有线适配器等),但至少会有两个。

所以在你的服务器应用中,你需要指示它将套接字绑定到正确的网络适配器上。

host = ''
port = 63001


bind(host,port)

在Python中,这样做是将套接字绑定到回环适配器(或者说127.0.0.1/localhost)。

在你的客户端应用中,你有:

host = '80.xxx.xxx.xxx'
port = 63001

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))

现在你的客户端试图连接到80.xxx.xxx.xxx(这是你的无线网络适配器)上的63001端口。

由于你的服务器在回环适配器上监听,而你的客户端在无线适配器上尝试连接,所以连接失败了,因为两者没有对上。

所以你有两个解决方案:

  1. 将客户端更改为连接到localhost,使用 host = 127.0.0.1

  2. 将服务器更改为绑定到你的互联网适配器,使用 host = 80.xxx.xxx.xxx

    第一个解决方案,使用localhost,只在你的服务器和客户端在同一台机器上时有效。localhost总是指向它自己(所以叫回环),无论你尝试哪个机器。因此,如果你决定将客户端/服务器放到互联网上,你必须绑定到一个在互联网上的网络适配器。

编辑补充:

好的,根据你最新的修改,它仍然无法工作,因为 65535 是可用的最大端口。

下面的回答是针对问题的最初版本。

在你发布的代码中,你在63001端口上监听(绑定),但你的客户端应用试图连接到80端口。这就是为什么你的客户端无法与服务器通信的原因。你的客户端需要使用63001端口而不是80端口进行连接。

另外,除非你在运行HTTP服务器(或者你的Python服务器能够处理HTTP请求),否则你真的不应该绑定到80端口。

在你的客户端代码中更改:

import socket
host = '80.xxx.xxx.xxx'
port = 63001

在你的服务器代码中:

import socket

host = ''
port = 63001

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostbyname(socket.gethostname()), port ))
1

在你的服务器脚本中,你设置了 port = 80,但是你并没有用到它。看起来服务器实际上是在63001端口上监听。而客户端则是连接到80端口。

如果你打算使用80端口,确保没有其他的HTTP服务器同时也在使用这个端口。

撰写回答