I/O错误(套接字错误):[错误号111] 连接被拒绝

15 投票
5 回答
173388 浏览
提问于 2025-04-15 21:06

我有一个程序,它使用urllib定期获取一个网址,但我遇到了一些间歇性的错误,比如:

输入/输出错误(套接字错误):[错误号 111] 连接被拒绝。

这个程序90%的时间都能正常工作,但剩下的10%时间会失败。如果在失败后立即重试获取,它又能成功。我搞不清楚为什么会这样。我检查过可用的端口,都是正常的。有没有什么调试的建议?

补充信息,错误堆栈信息是:

File "/usr/lib/python2.6/urllib.py", line 203, in open 
    return getattr(self, name)(url)

File "/usr/lib/python2.6/urllib.py", line 342, in open_http
    h.endheaders()

File "/usr/lib/python2.6/httplib.py", line 868, in endheaders
    self._send_output()

File "/usr/lib/python2.6/httplib.py", line 740, in _send_output
    self.send(msg)

File "/usr/lib/python2.6/httplib.py", line 699, in send
    self.connect()

File "/usr/lib/python2.6/httplib.py", line 683, in connect
    self.timeout)

File "/usr/lib/python2.6/socket.py", line 512, in create_connection
    raise error, msg

编辑 - 我在谷歌搜索了一下,结果并不太有帮助,我了解到我获取的服务器有时会拒绝连接,我该如何确认这不是我代码中的错误,而确实是这种情况呢?

5 个回答

3

我之前在使用EC2实例时遇到过这个问题(我当时在用couchdb来提供资源——未来可能考虑使用亚马逊的S3)。

首先要检查的一点是(假设你在用EC2),确保couchdb的端口已经添加到你的安全策略中的开放端口里。

我具体遇到的问题是:

"[Errno 111] 连接被拒绝"

这个问题出现在EC2上,当实例被停止再启动时。问题似乎是因为pid文件的竞争。对我来说,解决办法是通过以下命令完全且正确地杀掉couchdb:

pkill -f couchdb

然后再用以下命令重新启动:

/etc/init.d/couchdb restart
11

收到一个ECONNREFUSED的错误代码,意味着你的系统在尝试连接时,被对方拒绝了。所以如果这是个问题,那可能是你这边的系统出了问题,或者对方的系统有问题。

你可以用一种很特别的方法来捕捉这个错误,然后稍等一会儿再试,因为这样似乎有效:

# This is Python > 2.5 code
import errno, time

for attempt in range(MAXIMUM_NUMBER_OF_ATTEMPTS):
    try:
        # your urllib call here
    except EnvironmentError as exc: # replace " as " with ", " for Python<2.6
        if exc.errno == errno.ECONNREFUSED:
            time.sleep(A_COUPLE_OF_SECONDS)
        else:
            raise # re-raise otherwise
    else: # we tried, and we had no failure, so
        break
else: # we never broke out of the for loop
    raise RuntimeError("maximum number of unsuccessful attempts reached")

把那两个全大写的常量换成你喜欢的数字就可以了。

41

可以使用像Wireshark这样的网络数据包嗅探工具来观察发生了什么。你需要看到一个带有SYN标志的出站数据包,然后是一个带有SYN+ACK标志的入站数据包,最后再看到一个带有ACK标志的出站数据包。完成这些后,端口就被认为是在本地是开放的。

如果你只看到第一个数据包,而在等待几秒后出现错误信息,这说明另一方根本没有回应(可能是:网线拔掉了、服务器过载、数据包被错误处理而丢弃)。这时,你本地的网络系统会放弃连接尝试。如果你看到RST数据包,这表示对方实际上拒绝了连接。如果你看到“ICMP端口不可达”或者主机不可达的数据包,这说明防火墙或者目标主机告诉你这个端口实际上是关闭的。

当然,你不能指望服务随时都可用(想想你和数据之间可能出现的各种问题),所以你应该稍后再试。

撰写回答