Python套接字recv()由于硬件而挂起?

Posted

技术标签:

【中文标题】Python套接字recv()由于硬件而挂起?【英文标题】:Python socket recv() hangs due to hardware? 【发布时间】:2021-07-09 05:49:51 【问题描述】:

我在 python 套接字中遇到了 recv() 函数的问题。客户端在它们自己的线程(或进程)上运行,每个客户端在服务器上也有一个相应的监听线程。在客户端和服务器上都有频繁的消息发送和接收。有时代码工作正常并终止。但也有代码只是挂在 recv() 上的情况。

一个例子是当服务器已经接收到一些东西并发送(b“OK”)到客户端以表明它确实收到了消息并且客户端在发送上一条消息后执行recv(2)

服务器.py

...  # some previous code
server.recv(1024)  # This works fine
server.send(b"OK")  <-- blocks

客户端.py

...  # some previous code
client.send(a)  # Assume a is 1024 bytes, this works fine
client.recv(2)  <-- blocks
...  # Codes that triggers further actions on client and server

整个过程就挂在recv()上。所有套接字都设置为阻塞,因此必须是消息未正确接收的问题,因此该调用会阻止进一步的代码。

但这只是有时会发生,但并不总是如此,所以我知道整体逻辑和过程实际上运行良好。这是硬件分配该大小的内存/缓冲区速度慢的问题吗?有办法解决吗?

谢谢!

【问题讨论】:

你确定之前的recv调用没有收到OK吗? @user253751 是的,我很确定。我以这样的方式保留代码,以便服务器和客户端交替执行 send() 和 recv(),这样它就不会错误接收消息 【参考方案1】:

尝试使用sendAll() 以确保整个有效负载都由服务器和客户端发送。

【讨论】:

感谢您的回复。不幸的是,我尝试过 sendAll() 并且不时会出现相同的行为。 :-( 好吧,如果你告诉我问题时常出现,那很可能是同步问题。你确定你的代码没有在对方输入recv()之前发送send()吗?如果代码不是很大且不私密,您可以共享代码,以便我们可以在我们的机器上试用并调试它。 您好,我刚才又查了一下,认为不存在我把几个send()放在一起导致错误接收的情况。抱歉,我想我不能分享代码,因为它很笨重,而且也是一个私人项目 :-( 我很想听听“同步问题”。你是什么意思? 我所说的“同步”问题是服务器在客户端开始监听之前发送数据(或相反)。没有代码我不能保证,但如果你告诉我客户端和服务器有时会很好,而其他时候却不是,那么问题很可能是两个实体之间的时间问题。 对这个问题的跟进。刚刚通过减少用于接收更大信息的函数中的缓冲区大小来解决它。不完全确定这是如何导致上述问题的,但我的猜测是使用该函数接收相对较小的消息可能会出现问题并被阻止。但无论如何,“同步问题”提示让我考虑了一下,非常感谢!【参考方案2】:

假设您使用的是 TCP,您可能会遇到 Nagle 缓冲算法。其目的是通过将小数据包收集到一个较大的数据包中来提高效率。

https://en.wikipedia.org/wiki/Nagle%27s_algorithm

【讨论】:

感谢您的回复。我认为可能是这种情况,但我会先尝试一下(通过每次发送“更大”的确认消息)。但另一方面,如果是这样的话,为什么每次我运行它时它的行为都不一样,是否有一个大小阈值肯定会触发套接字在 python 实现中发送消息? 嗨,我刚刚实现了这个,遗憾的是它似乎并没有解决问题。

以上是关于Python套接字recv()由于硬件而挂起?的主要内容,如果未能解决你的问题,请参考以下文章

面临 recv() 和 send() winsock api 的问题。 Recv() 在接收最后一个数据包时挂起

来自java客户端的Python套接字recv

Python异步套接字recv不起作用

如果在超时发生之前没有收到数据,Python 的 socket.recv() 会为非阻塞套接字返回啥?

Python套接字,从服务器请求文件然后等待接收它

如何在由于库函数而挂起的函数上实现超时? [复制]