套接字错误:尝试连接套接字时发生[Errno 111]

3
我正在尝试编写代码,使得客户端连接到服务器的默认端口号。然后,服务器向客户端发送另一个端口号。现在,客户端将连接到新的端口号。
客户端:
import socket
import sys
import os
import signal
import time
s = socket.socket()
s.connect(("127.0.0.1", 6667))
line = s.recv(1024)
if line.strip():
    port = int(line)
    s.close()
    soc = socket.socket()
    soc.connect(("127.0.0.1", port))
    print soc.recv(1024)
    soc.close()
else:
    s.close()

服务器:

import socket
import sys
import os
import signal
import time
port = 7777
s = socket.socket()
s.bind(("127.0.0.1", 6667))
s.listen(0)
sc, address = s.accept()
print address
sc.send(str(port))
sc.close()
s.close()
sock = socket.socket()
sock.bind(("127.0.0.1", port))
soc, addr = sock.accept()
print addr
soc.send("Success")
soc.close()
sock.close()

当我执行这段代码时,客户端和服务器端都出现了以下错误。
服务器端:
('127.0.0.1', 36282)
Traceback (most recent call last):
  File "server.py", line 17, in <module>
    soc, addr = sock.accept()
  File "/usr/lib/python2.7/socket.py", line 202, in accept
    sock, addr = self._sock.accept()
socket.error: [Errno 22] Invalid argument

客户端:

Traceback (most recent call last):
  File "client.py", line 13, in <module>
    soc.connect(("127.0.0.1", port))
  File "/usr/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
socket.error: [Errno 111] Connection refused

有人能够解释这些错误的原因并提供这些错误的解决方案吗?


2
在调用sock.bind(("127.0.0.1", port))之后,您似乎遗漏了sock.listen(0)。另外,请考虑一下如果在服务器开始监听连接之前,客户端收到端口号并尝试连接会发生什么。 - Michael Petch
可以尝试使用"^",但要注意变量名称...例如sscsock等,特别是如果你会在这里发布代码。 - wenzul
@MichaelPetch:为什么不把这个变成一个答案呢? - alk
@ Michael Petch:谢谢,它起作用了。我是socket编程的新手,这很有帮助。 - dynamo
1个回答

1
在你能够listen一个TCP/IP套接字(基于连接的流式套接字)之前,你需要使用bind来分配一个套接字(使用socket.socket()创建)。然后你需要做listen来准备它接受传入的连接,最后在准备好的套接字上执行accept
在调用sock.bind(("127.0.0.1", port))之后,你似乎缺少了sock.listen(0)Python文档对TCP/IP的细节介绍得很少,但它确实这样说:

请注意,服务器必须执行序列socket()bind()listen()accept()(可能重复accept()以服务于多个客户端),而客户端只需要序列socket()、connect()。还要注意,服务器不会在它正在监听的套接字上发送/接收数据,而是在accept()返回的新套接字上。

Python的socket模块是基于Berkeley Socket模型构建的。你可以在link找到更详细的Berkeley Sockets信息。特别是对于bind,它有以下解释:

bind()将套接字绑定到一个地址。当使用socket()创建套接字时,仅分配协议族,但不分配地址。必须使用bind()系统调用执行此关联操作,然后套接字才能接受来自其他主机的连接

同时考虑一下,如果客户端在服务器开始侦听连接之前(在此示例中为端口7777)发送端口号并尝试连接会发生什么。虽然这不是问题的原因,但我想完整地介绍一下这种情况。你可以考虑的一些事情是,在调用端口7777套接字上的listen之前不要关闭端口6667套接字。在调用listen之后,可以关闭第一个套接字。在客户端读取端口号后,可以等待服务器关闭第一个连接(端口6667),然后连接到端口7777。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接