Python socket 连接异常

22 投票
2 回答
144132 浏览
提问于 2025-04-18 18:11

我正在进行一个套接字连接的操作,想要改善异常处理,但遇到了困难。每当我用一个无效的参数调用 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异常。我也试过直接用:

except Exception, msg:

如果我没记错的话,这样可以捕获任何异常,但结果仍然没有。非常感谢能得到帮助。另外,当出现不想要的异常时,使用sys.exit退出程序可以吗?

谢谢

2 个回答

9

你最后提到的通用异常问题在于冒号的位置。冒号应该放在整个异常的后面,而不是放在except语句后面。所以,要捕获所有异常,你需要这样写:

except Exception,msg:

不过从Python 2.6版本开始,你应该使用as语句,而不是用逗号,像这样:

except Exception as msg:

我运行代码的时候没有问题(注意你需要在连接方法中传入一个元组)。如果你想专门捕获socket错误,那么你需要捕获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
25

如果你选择了一个随机但有效的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派生出来的,因此会被上面的异常处理部分捕获。

撰写回答