在网络编程当中,Socket异常是较为常见的问题。要是这些异常没有被及时处理,就会对程序的稳定运行产生严重影响。下面会为大家详细剖析几种常见的Socket异常。
异常基础规则
Socket默认的连接时长为60秒,在这60秒里,如果没有像读写数据这样的心跳交互,连接就会自动关闭,这是很多Socket异常出现所依据的一个基础性规则,比如在一些数据交互频率低的场景中,就容易因为这个时间限制致使连接自动断开,为避免连接自动关闭,就需要在60秒内开展有效的数据读写操作。
Connect reset by peer
若一端的Socket被关闭,这关闭情况分为主动关闭和因异常退出而关闭两种。当另一方仍发送数据时,发送的第一个数据包就会引发这个异常。存在这样一种情况,某系统中客户端突然崩溃退出,进而致使Socket关闭。而服务器端并不知情,依旧在发送数据,这样便触发了这个异常。遇到这种问题时,要去检查Socket关闭的原因,避免在自己不知情的情况下继续发送数据。
Connection reset
一端退出后,没有关闭连接。这时另一端在读取连接中的数据时,就会抛出这个异常。当网络连接通过防火墙时,因为防火墙有超时机制,长时间没有数据传输,就会关闭TCP会话。之后再进行读写操作,就会导致此异常。比如说,某公司网络通过防火墙,一段代码由于长时间未发送数据,导致会话被关闭,再读取数据时就报错了。需要留意防火墙的设置以及网络连接的数据传输情况。
ServerSocket创建异常
该异常出现在服务器端执行new ServerSocket(port)
操作时,port
是整型值,取值范围为0到65536 。这个异常常因端口被占用或服务未启动导致。在某个项目中,服务器启动新的ServerSocket
时,因端口被其他程序占用而报错。可以通过查看端口占用情况,释放被占用的端口。
客户端进行new Socket(ip, port)
操作时会出现异常,原因有两个。一个原因是,具有该ip
地址的机器找不到,这表明从当前机器到指定ip
没有路由。另一个原因是,该ip
存在,然而找不到指定的端口进行监听。曾经有客户端在连接服务器时,由于ip
地址写错而无法连接。我们要仔细检查客户端的ip
和port
是否正确。
Socket is closed
该异常有可能在客户端发生,也有可能在服务器端发生,这是由于己方主动关闭连接之后,又对网络连接做了读写操作。在调试程序的时候,客户端先关闭了Socket
,接着又尝试发送数据,从而触发了这个异常。主动关闭连接后,就不要再进行读写操作了。
def test_main():
s_conn = pika.BlockingConnection(
pika.ConnectionParameters('127.0.0.1',
heartbeat_interval=10,
socket_timeout=5,
credentials=pika.PlainCredentials(USER, PWD)))
# ....
异常处理方法
:param int heartbeat_interval: How often to send heartbeats.
Min between this value and server's proposal
will be used. Use 0 to deactivate heartbeats
and None to accept server's proposal.
出现问题后,要先检查客户端的ip
是否正确,还要检查客户端的port
是否正确。若两者都正确,就从客户端ping
一下服务器,看看能不能ping
通。要是服务器把ping
禁掉,那就需要用其他方法。若能ping
通,接着看服务器端监听指定端口的程序有没有启动。在某项目中,按照这个流程排查,很快就解决了Socket
连接异常问题。
大家遇到上述这类Socket
异常的时候,有没有尝试过其他解决办法?如果尝试过,欢迎在评论区分享你的经验,还请点赞并且分享这篇文章,这样能让更多人获取这些实用信息!
import threading,time
#开启一个线程,每隔20s,执行一次心跳
def timesleep(n):
for i in range(n):
time.sleep(20)
# heartbeat=0,意味着不检测心跳,server端将不会主动断开连接。但是并不起作用,
# process_data_events 方法,类似 heartbeat 操作,可以保持与 rabbitmq 的通信。
# 在执行长时间任务时,定时调用 process_data_events 方法,就不会丢失连接
self.connection.process_data_events()
message_thread = threading.Thread(target=timesleep, args=(3600*24,))
message_thread.start()
发表评论