【问题标题】:Python socket connection exceptionPython套接字连接异常
【发布时间】:2014-08-22 13:07:21
【问题描述】:

我有一个套接字连接正在进行,我想改进异常处理,但我被卡住了。每当我使用无效参数调用socket.connect(server_address) 时,程序都会停止,但似乎不会引发异常。这是我的代码:

import socket
import sys
import struct
class ARToolkit():
    
    def __init__(self):
        self.x = 0
        self.y = 0
        self.z = 0
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.logging = False
    
    def connect(self,server_address):
        try:
            self.sock.connect(server_address)
        except socket.error, msg:
            print "Couldnt connect with the socket-server: %s\n terminating program" % msg
            sys.exit(1)
    
    def initiate(self):
        self.sock.send("start_logging")
    
    def log(self):
        self.logging  = True  
        buf = self.sock.recv(6000)
        if len(buf)>0:
            nbuf = buf[len(buf)-12:len(buf)]
            self.x, self.y, self.z = struct.unpack("<iii", nbuf) 
    
    def stop_logging(self):
        print "Stopping logging"
        self.logging = False
        self.sock.close()
            

这个类可能看起来有点奇怪,但它用于从另一台运行 ARToolKit 的计算机接收坐标。无论如何,问题出在函数connect()

def connect(self,server_address):
    try:
        self.sock.connect(server_address)
    except socket.error, msg:
        print "Couldnt connect with the socket-server: %s\n terminating program" % msg
        sys.exit(1)

如果我使用随机 IP 地址和端口号调用该函数,整个程序就会停止在该行:

self.sock.connect(server_address)

我读过的文档指出,如果出现错误,它将抛出 socket.error-exception。我也试过了:

except Exception, msg:

如果我没记错的话,这会捕获任何异常,但它仍然不会产生任何结果。我将非常感谢您的帮助。另外,当出现不需要的异常时,是否可以使用 sys.exit 退出程序?

谢谢

【问题讨论】:

  • 你如何开始你的程序?你确定你的打印不会进入 /dev/null 之类的吗?还有一些异常从 BaseException 继承,所以如果你真的很绝望,你也可以尝试捕捉它(这包括 sys.exit 和键盘中断)

标签: python sockets exception


【解决方案1】:

如果您选择了一个随机但有效的 IP 地址和端口,socket.connect() 将尝试与该端点建立连接。默认情况下,如果没有为套接字设置显式超时,它会在这样做时阻塞并最终超时,引发异常socket.error: [Errno 110] Connection timed out

我机器上的默认超时时间是 120 秒。也许您没有等待足够长的时间让socket.connect() 返回(或超时)?

您可以尝试像这样减少超时:

import socket

s = socket.socket()
s.settimeout(5)   # 5 seconds
try:
    s.connect(('123.123.123.123', 12345))         # "random" IP address and port
except socket.error, exc:
    print "Caught exception socket.error : %s" % exc

请注意,如果为套接字显式设置了超时,则异常将是 socket.timeout,它派生自 socket.error,因此将被上述 except 子句捕获。

【讨论】:

  • 谢谢兄弟!这就是问题所在,我手动终止了程序而不是等待超时。
  • 那么如果超时设置为None,你说120秒后还是会出现超时异常(或者其他默认)?如何获取/设置此默认值?
  • @ItamarKatz:超时是系统定义的。在 Linux(和其他 Unix 变体)中,它由建立连接的重试次数间接控制 - 实际上是尝试获得对 SYN 数据包响应的次数。您可以使用cat /proc/sys/net/ipv4/tcp_syn_retries 查看设置。您也可以通过修改该特殊文件来更改它。退休通常使用指数退避算法发送,该算法增加重试之间的间隔,例如3、7、15、31 秒。我的 Linux 系统将 tcp_syn_retries 设置为 5,大约需要 120 秒。
  • @ItamarKatz:更改该设置会影响系统上的所有进程,因此我建议不要这样做。如果您想设置超时,请使用socket.settimeout()。如果你想要一个大于你的操作系统允许的超时时间,你需要通过在 Python 中执行你自己的重试来处理它。
  • 非常感谢。实际上,我正在尝试与使用超时进行限制相反-我的服务器脚本抛出 [Errno 110] Connection timed out 异常,我不明白为什么,那就是我希望它“永远”等待。我正在使用select,然后才使用socket.recv 读取,这就是为什么我不明白为什么会发生此异常。
【解决方案2】:

最后一个一般例外的问题是冒号位置。它需要在整个异常之后,而不是在 except 语句之后。因此,要捕获您需要执行的所有异常:

except Exception,msg:

但是,从 Python 2.6+ 开始,您应该使用 as 语句而不是像这样的逗号:

except Exception as msg:

我能够很好地运行代码(请注意,您需要向 connect 方法添加一个元组)。如果您只想专门捕获套接字错误,那么您需要将 socket.error 类除外。就像你一样:

except socket.error as msg:

如果您想确保输入了一个元组,只需添加另一个异常循环:

except socket.error as msg:
    print "Socket Error: %s" % msg
except TypeError as msg:
    print "Type Error: %s" % msg

【讨论】:

  • 感谢您的输入,但在更改超时后,即使我没有使用“as”,我现在也能够捕获异常。冒号错位是一个错字。
猜你喜欢
  • 1970-01-01
  • 2013-04-24
  • 2016-06-24
  • 2019-10-21
  • 1970-01-01
  • 2013-09-08
  • 2021-12-01
  • 2013-06-29
  • 1970-01-01
相关资源
最近更新 更多