如何解锁被阻塞的套接字?

0 投票
4 回答
4300 浏览
提问于 2025-04-16 08:22

概述: 我的程序有时候会遇到一种情况,它想通过一个套接字(socket)发送数据,但这个套接字被阻塞了,因为它在等待之前一个命令的响应,而那个响应根本没有到来。有没有办法让这个套接字解锁,然后继续使用它?如果没有,那我怎么能测试这个套接字是否被阻塞,这样我就可以关闭它并重新打开一个新的?(我一开始需要的是阻塞套接字)

详细信息: 我通过两个套接字连接到一个服务器。套接字1用于一般命令的通信,套接字2用于中止正在运行的命令。中止命令可以随时发生,而且频率很高。每个通过套接字1发送的命令都会收到一个响应,比如:

socket1 send: set command data
socket1 read: set command ack

在发送和读取之间总是有一段时间,因为服务器在命令执行完成之前不会发送任何东西。

为了中断正在进行的命令,我会通过另一个套接字连接并发出中止命令。然后我再用套接字1发出新的命令。

我发现,有时候在发出中止命令后,通过套接字1发出的命令会让程序卡住。看起来套接字1被阻塞了,它在等待之前发出的命令的响应,而那个命令并没有返回(而且被中断了)。虽然通常情况下它能正常工作,但有时却不行(我没有写服务器的代码)。

在这些情况下,有没有办法让我检查套接字1是否被阻塞在等待读取,如果是的话,能否放弃这个读取并继续?或者有没有其他方法让我检查,以便我可以关闭这个套接字并重新开始?

谢谢!

更新1:感谢大家的回答。至于我为什么使用阻塞套接字,是因为我用这段代码控制一台类似CNC的机器,我需要知道我让它执行的命令什么时候执行完。服务器在执行完成后会返回一个确认信号(ACK),所以这似乎是处理它的好方法。我喜欢非阻塞的重构想法,但我想不出其他方法来获取命令完成的信息。我会看看选择(select)和其他选项。

4 个回答

0

套接字应该是全双工的,也就是说,它可以同时进行读和写。如果在Python中,一个线程在写数据到套接字的时候,另一个线程却被阻止去读取同一个套接字,那我认为这是Python的一个重大错误。在我用过的其他编程语言中是不会出现这样的情况的。

2

解决这个问题的传统方法是使用 select。在写数据之前,先检查一下这个连接(socket)是否可以写,如果不可以,就得先做其他事情(比如先等一下回应)。在 select 之上,Python 提供了 asyncore 模块,可以帮助处理这种情况。再往上一个层次,Twisted 是一个完整的框架,用来处理消息的异步处理。

4

我不是想跟你争论,但你说你需要阻塞套接字,然后又提到了一些非常好的理由说明你其实需要非阻塞套接字。我建议你考虑改用非阻塞的方式。

除此之外,我知道的唯一判断套接字是否被阻塞的方法,就是你的程序调用了 recv 或它的变种,但还没有返回。也许还有其他人知道我不知道的API,但在 recv 调用之前设置一个“阻塞”的布尔值,然后在之后清除它,可能是获取这个信息的最佳方法。不过,你其实不想这么做。相信我,从长远来看,改进代码会更有价值。

撰写回答