当服务器很慢时,写入客户端返回 EWOULDBLOCK [英] Write to the client returns EWOULDBLOCK when server is slow

查看:37
本文介绍了当服务器很慢时,写入客户端返回 EWOULDBLOCK的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在特定时间间隔后在套接字中写入一些数据.我有两个线程,一个线程维护 TCP 连接,另一个线程生成数据.

I am trying to write some data in the socket after specific time interval. I have two threads, one thread maintaining the TCP connection, and another thread generating data.

数据生成器生成数据,并将其写入共享内存.服务器线程从共享内存中读取数据,并发送给客户端.

The data generating therad generates data, and writes it to a shared memory. The server threadreads data from the shared memory, and sends it to the client.

但是,当数据生成线程变慢时,当涉及大量计算时,服务器线程在尝试写入客户端时会收到 EWOULDBLOCK 错误.但是,令人惊讶的是,从客户端来看,并没有这样的错误.

But, when the data generating thread becomes slow, when a lot of calculations involved, the server thread gets a EWOULDBLOCK error when trying to write to the client. But, surprisingly, from the client side, there is no such error.

如果我没记错的话,当服务器比客户端快并且在再次写入之前没有完全读取套接字缓冲区时,会返回 EWOULDBLOCK 错误.但是,这里的情况完全相反.

If I am not wrong, EWOULDBLOCK error is returned when server is faster than client and the socket buffer is not completely read before it gets written again. But, here the case is totally opposite.

是不是因为服务器一直处于休眠状态,直到数据生成线程完成(数据线程具有更高的优先级).

Can it be because the server therad is kept on sleep till the data generation thread completes( data thread has a higher priority).

有人能解释一下这里可能发生的事情吗?

Can somebody explain what might be happening here?

推荐答案

EWOULDBLOCK 在您使用非阻塞套接字并且内核的传出数据缓冲区中没有足够空间用于该套接字容纳任何您要发送的数据.如果客户端读取速度太慢,可能会发生这种情况,但如果服务器尝试一次发送大量数据,也会发生这种情况(即使客户端速度很快);例如,如果您的计算线程花费很长时间计算数据,然后在计算结束时突然一次传递了超过 300,000 字节的数据,您的服务器线程可能会执行以下操作:

EWOULDBLOCK is returned when you are using a non-blocking socket and there is not enough space in the kernel's outgoing-data-buffer for that socket to hold any of the data you want to send. That could happen if the client is reading too slowly, but it could also happen (even with a fast client) if the server tries to send a large amount of data at once; for example, if your calculation thread spend a long time calculating data, and then at the end of the calculation suddenly passed over 300,000 bytes of data at once, your server thread might do something like this:

  1. 看到共享内存区域中有一些数据可用,是时候开始发送了!
  2. 使用 len=300000 调用 send().send() 吸收尽可能多的数据,以适应内核的传出套接字数据缓冲区(例如 131,072 字节),并返回 131072 以表明它做了什么.
  3. 现在您的服务器线程发现它还有 168928 字节的数据要发送,因此它再次使用 len=168928 调用 send().此时,内核的outgoing-socket-data-buffer 仍然完全满了(因为还没有机会发送任何数据包),所以send() 返回EWOULDBLOCK.

一般来说,只要您使用的是非阻塞套接字,EWOULDBLOCK 就是您的代码需要处理的.我通常的处理方式是:

In general, as long as you are using non-blocking sockets, EWOULDBLOCK is something your code will need to handle. The way I usually handle it is:

  1. 在 select()(或 poll() 等)中等待,直到套接字返回就绪可写
  2. 当 select()/poll() 指示套接字已准备好写入时,在套接字上调用 send() 直到您发送了所有可用数据,或者直到 send() 返回 EWOULDBLOCK(以发生者为准)首先).
  3. 如果您在第 2 步中获得了 EWOULDBLOCK,请转到 1.

那样你的发送线程将总是尽可能快地将传出数据提供给内核,但不会更快——也就是说,你不会浪费任何 CPU 做忙循环,但你也不会浪费时间在流程中插入任何不必要的延迟.

That way your send-thread will always feed the outgoing data to the kernel as fast as possible, but no faster -- i.e. you don't waste any CPU do busy-looping, but you also don't waste time by inserting any unnecessary delays into the process.

这篇关于当服务器很慢时,写入客户端返回 EWOULDBLOCK的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆