【问题标题】:I/O error(socket error): [Errno 111] Connection refusedI/O 错误(套接字错误):[Errno 111] 连接被拒绝
【发布时间】:2010-04-01 07:28:46
【问题描述】:

我有一个使用 urllib 定期获取 url 的程序,我看到断断续续 像这样的错误:

I/O 错误(套接字错误):[Errno 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

编辑 - 谷歌搜索不是很有帮助,我从中得到的是服务器 我有时会拒绝连接,我如何验证它不是我的代码中的错误 真的是这样吗?

【问题讨论】:

  • 什么是“我试图查看是否有可用的端口,它们是可用的。”意思是?如果你收到一个 ECONNREFUSED 是肯定的响应 - 在原始套接字层 - 从远程主机说“我听到你在敲门,但没有人在听”;这通常是由于服务器过载造成的。您的重试表明这是暂时的,您的 90/10% 比率也是如此。如何证明它不是你的代码? Telnet 到服务器端口。编写一个 python 套接字层例程来尝试连接并给出命中/拒绝率。

标签: python sockets urllib


【解决方案1】:

使用像Wireshark 这样的数据包嗅探器来查看发生了什么。您需要看到一个带有 SYN 标记的数据包传出,一个带有 SYN+ACK 标记的传入,然后是一个带有 ACK 标记的传出。之后,该端口在本地被认为是开放的。

如果您只看到第一个数据包并且在等待几秒钟后出现错误消息,则另一方根本没有响应(例如:拔掉电缆、服务器过载、错误的数据包被丢弃)并且您的本地网络堆栈中止连接尝试。如果您看到 RST 数据包,则主机实际上拒绝了连接。如果您看到“ICMP Port unreachable”或主机无法访问的数据包,防火墙或目标主机会通知您该端口实际上已关闭。

当然,您不能期望服务始终可用(考虑您和数据之间的所有故障点),因此您应该稍后再试。

【讨论】:

    【解决方案2】:

    得到一个 ECONNREFUSED errno 意味着 你的 内核在另一端被拒绝连接,所以如果它是一个错误,它要么在你的内核中,要么在另一端。 您可以做的是以非常具体的方式捕获错误并稍后重试,因为这似乎有效:

    # 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")
    

    用您喜欢的数字替换两个全大写常量。

    【讨论】:

      【解决方案3】:

      我之前在我的 EC2 实例上遇到过这个问题(我正在使用 couchdb 来提供资源——我正在考虑将来使用 Amazon 的 S3)。

      要检查的一件事(假设 Ec2)是 couchdb 端口已添加到您的安全策略中的开放端口中。

      我特地遇到过

      “[Errno 111] 连接被拒绝”

      在实例停止和启动时通过 EC2。问题似乎是 pidfile 竞赛。我的解决方案是通过以下方式(完全正确地)杀死 couchdb:

      pkill -f couchdb
      

      然后重启:

      /etc/init.d/couchdb restart
      

      【讨论】:

        【解决方案4】:

        我不确定是什么原因造成的。您可以尝试查看您的 socket.py(我的版本不同,因此跟踪中的行号不匹配,恐怕其他一些细节也可能不匹配)。

        无论如何,将您的 url 获取代码放在 try: ... except: ... 块中,并通过短暂的暂停和重试来处理它似乎是一个好习惯。您尝试获取的 URL 可能已关闭或加载过多,而这些都是您只能通过重试才能处理的内容。

        【讨论】:

          【解决方案5】:

          似乎服务器运行不正常,所以请确保通过终端使用

          telnet ip port
          

          例子

          telnet localhost 8069
          

          会返回connected to localhost所以表示连接没有问题 否则返回Connection refused表示连接有问题

          【讨论】:

            猜你喜欢
            • 2016-01-31
            • 2013-12-19
            • 1970-01-01
            • 1970-01-01
            • 2012-06-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多