我的IP和端口应该设置成什么,以避免errno 10061错误?

-2 投票
2 回答
520 浏览
提问于 2025-04-18 09:57

服务器代码:

import socket
import base64

filename = open("received.xvid","ab")

TCP_IP = '127.0.0.1'
TCP_PORT = 5005
BUFFER_SIZE = 1024

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((TCP_IP, TCP_PORT))
s.listen(1)

conn, addr = s.accept()
data = conn.recv(16)
filesize = int(data)
iter = filesize//BUFFER_SIZE
i = 0

while (i < iter):
    data = conn.recv(BUFFER_SIZE)
    filename.write(data.decode('base64'))
    if not data:
        continue
    i = i + 1

data = conn.recv((filesize - (iter*BUFFER_SIZE)))
filename.write(data.decode('base64'))
filename.close()

conn.close()

客户端代码:

import socket
import time
import base64

TCP_IP = '127.0.0.1'
TCP_PORT = 5005
BUFFER_SIZE = 1024

filename = open("test.xvid","rb")
MESSAGE = base64.b64encode(filename.read())
filesize = '%16s'%len(MESSAGE)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((TCP_IP, TCP_PORT))
s.send(filesize)
time.sleep(1)
s.send(MESSAGE)
s.close()

当我运行客户端代码时,出现了“socket.error: [Errno 10061] 无法连接,因为目标机器主动拒绝了连接”的错误。我不明白为什么会这样。我应该在TCP_IP和TCP_PORT的位置填什么才能让代码正常工作呢?

这是我输入命令netstat -tnl后得到的结果。

这个命令可以显示协议统计信息和当前的TCP/IP网络连接。

NETSTAT [-a] [-b] [-e] [-f] [-n] [-o] [-p proto] [-r] [-s] [-x] [-t] [interval]

-a 显示所有连接和监听端口。 -b 显示每个连接或监听端口所涉及的可执行文件。在某些情况下,知名的可执行文件会托管多个独立的组件,这时会显示创建连接或监听端口的组件序列。可执行文件的名称会在底部的[]中,而上面是它调用的组件,依此类推,直到TCP/IP为止。请注意,这个选项可能会耗时,并且如果权限不足会失败。 -e 显示以太网统计信息。可以与-s选项结合使用。 -f 显示外部地址的完全合格域名(FQDN)。 -n 以数字形式显示地址和端口号。 -o 显示与每个连接相关的进程ID。 -p proto 显示指定协议(proto)的连接;proto可以是TCP、UDP、TCPv6或UDPv6中的任何一个。如果与-s选项一起使用以显示每个协议的统计信息,proto可以是IP、IPv6、ICMP、ICMPv6、TCP、TCPv6、UDP或UDPv6中的任何一个。 -r 显示路由表。 -s 显示每个协议的统计信息。默认情况下,显示IP、IPv6、ICMP、ICMPv6、TCP、TCPv6、UDP和UDPv6的统计信息;可以使用-p选项指定默认值的子集。 -t 显示当前连接的卸载状态。 -x 显示NetworkDirect连接、监听器和共享端点。 -y 显示所有连接的TCP连接模板。不能与其他选项结合使用。 interval 重新显示选定的统计信息,每次显示之间暂停interval秒。按CTRL+C停止重新显示统计信息。如果省略,netstat将一次打印当前的配置信息。

2 个回答

2
  • 如果这种情况总是发生,说明机器是存在的,但在指定的端口上没有服务在监听,或者有防火墙在阻止你。
  • 如果偶尔发生这种情况,但重试后成功了,那可能是因为服务器的请求队列满了。

当你在等待被 accept 时,你会被放在一个请求队列中。这个队列是有限的,而且通常很短,像1、2或3这样的值是很常见的。因此,操作系统可能无法将你的请求排队,等着 accept 来处理。

这个请求队列的大小是 listen 函数的一个参数——所有语言和平台在这方面基本上都是一样的。如果你控制服务器,这个参数通常是可以配置的,可能是从某个设置文件或注册表中读取的。你可以查一下如何配置你的服务器。

无论你是否能增加服务器的请求队列大小,你的客户端代码中都需要有重试的逻辑来应对这个问题,因为即使有一个很长的请求队列,服务器在那个时间点也可能会接收到很多其他请求。

还有一种少见的情况是,如果NAT路由器的端口映射用尽,也可能会出现这个错误。不过我觉得这种可能性不大,因为路由器在达到极限之前,可以同时处理64K个连接到同一个目标地址/端口。

你也可以在这里查看更多原因:

0

当我在同一台机器上运行服务器和客户端时,一切都很好。但当我在不同的机器上运行它们时,问题就出现了。

好的,我知道你的问题出在哪里了。

 TCP_IP = '127.0.0.1'

你把这个IP地址写死在了服务器和客户端里。这个特殊的IP地址表示这台机器,只有这台机器。当你在bind()中使用它时,服务器只会监听来自同一台机器的连接。当你在connect()中使用它时,客户端会尝试连接到同一台机器上的服务器。

如果你想让服务器能够接受来自任何机器的连接,像你可能想要的那样,你需要在调用bind时使用特殊的IP地址0.0.0.0。(一个完整的生产用服务器需要做一些稍微复杂的事情,但对于像这样的测试程序来说,这已经足够了。)

如果你想让客户端连接到另一台机器上的服务器,它需要把另一台机器的DNS名称作为命令行参数传入,并通过getaddrinfo来获取要连接的IP地址。

你应该买一本并阅读UNIX网络编程,第1卷,第3版UNIX环境高级编程。它们虽然贵,但非常值得。它们会详细解释上面的建议,并教你许多其他你需要知道的东西,如果你想编写一个完整的网络服务器或客户端的话。(确保你买的是UNIX网络编程的第三版;早期版本包含了一些过时的内容,你不需要了解。UNIX网络编程的第二卷也很有价值,但对你当前的情况适用性不强。高级编程...也不那么直接相关,特别是如果你是在Windows上,因为我从错误信息的措辞中猜测你是在Windows上。)

撰写回答