- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
过去几天,我在epoll上苦苦挣扎,现在处在茫茫荒野之中;)
互联网上有很多信息,很明显,系统人中有很多信息,但是我可能服用过量并且有些困惑。
在我的服务器应用程序(后端到nginx)中,我正在等待ET模式下来自客户端的数据:event_template.events = EPOLLIN | EPOLLRDHUP | EPOLLET
当我注意到nginx响应502时,一切都变得很好奇,尽管我可以看到成功的send()在我这一边。我跑钢丝
嗅探并意识到我的服务器向网络上的另一台计算机发送(尝试并获取RST)数据。因此,我认为套接字描述符无效,这是一种“未定义的行为”。最后,我发现在第二个recv()上,我得到了零字节,这意味着必须关闭连接,并且不再允许将数据发送回去。但是,我连续从epoll获得的不仅是EPOLLIN,而且是EPOLLRDHUP。
问题:当在EPOLLRDHUP处理过程中recv()返回零且稍后关机(SHUT_WR)时,是否必须关闭套接字以进行读取?
简而言之,从套接字读取:
std::array<char, BatchSize> batch;
ssize_t total_count = 0, count = 0;
do {
count = recv(_handle, batch.begin(), batch.size(), MSG_DONTWAIT);
if (0 == count && 0 == total_count) {
/// @??? Do I need to wait zero just on first iteration?
close();
return total_count;
} else if (count < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
/// @??? Will be back with next EPOLLIN?!
break ;
}
_last_error = errno;
/// @brief just log the error
return 0;
}
if (count > 0) {
total_count += count;
/// DATA!
if (count < batch.size()) {
/// @??? Received less than requested - no sense to repeat recv, otherwise I need one more turn?!
return total_count;
}
}
} while (count > 0);
最佳答案
Questions: Do I have to close socket just for reading when recv() returns zero and shutdown(SHUT_WR) later on during EPOLLRDHUP processing?
0
接收到
recv()
返回值后,您知道该连接在网络层至少关闭了一半。您将不会再收到任何东西,我也不希望在边缘触发模式下运行的EPoll能够进一步宣传其阅读准备,但这本身并不需要任何特殊操作。如果写端保持打开状态(从本地 Angular 看),则可以继续使用
write()
或
send()
,尽管您将没有确认收到发送内容的机制。
recv()
通过返回
0
发出文件结束信号时停止使用它。请注意,对描述符进行
close()
编码会自动将其从注册它的所有Epoll兴趣集中删除,但前提是没有其他打开文件描述符引用相同的打开文件描述。
close()
为止,即使您无法通过它成功通信,它也仍然有效。在此之前,没有理由期望您尝试通过它发送的消息会到达除原始远程端点之外的任何其他地方。尝试发送可能会成功,或者即使数据永远不会到达远端,也可能会发送尝试,或者尝试可能会失败,并出现几种不同的错误之一。
/// @??? Do I need to wait zero just on first iteration?
/// @??? Will be back with next EPOLLIN?!
recv()
失败并显示
EAGAIN
或
EWOULDBLOCK
,则EPoll可能会在以后的调用中很好地表示已准备就绪。不过,下一个不必一定要这样做。
/// @??? Received less than requested - no sense to repeat recv, otherwise I need one more turn?!
recv()
不会返回任何数据,并且如果您在EPoll中使用边沿触发模式,则假定相反的做法很危险。在这种情况下,您应该继续以非阻塞模式或
recv()
进入
MSG_DONTWAIT
,直到使用
EAGAIN
或
EWOULDBLOCK
调用失败。
As far as I now know, send() may also return -1 and EAGAIN which means that I'm supposed to subscribe on EPOLLOUT and wait when kernel buffer will be free enough to receive some data from my me. Is this right?
send()
肯定会因
EAGAIN
或
EWOULDBLOCK
而失败。它也可以成功,但是发送的字节数少于请求的字节数,您应该为此做好准备。无论哪种方式,通过在文件描述符上订阅EPOLLOUT事件进行响应都是合理的,以便稍后恢复发送。
But what if client won't wait so long?
send()
失败,并会出现其他错误。如果您仅在描述符上注册了EPOLLOUT事件,那么我怀疑是否有可能陷入这种尝试永远不会发生的情况,因为不会发出进一步的事件。即使您主要的兴趣是写作,也可以通过注册并正确处理
EPOLLRDHUP
事件来进一步降低这种可能性。
EPOLLRDHUP
可能不会有用,并且您更有可能将陈旧的连接无限期地卡在EPoll中。可能需要通过每个FD超时来解决这种可能性。
Or, may I call blocking send(anyway, I'm sending on a different thread) and guarantee the everything what I send to kernel will be really sent to peer because of setsockopt(SO_LINGER)?
send()
。唯一的缺点是您不能在此之上实现超时,但是除此之外,如果该线程在发送数据或接收更多要发送的数据时发生阻塞,该线程将做什么?
SO_LINGER
与它有什么关系。内核将尽一切努力通过
send()
调用将您已经分派(dispatch)的数据发送到远程对等设备,即使您在数据仍处于缓冲状态时对套接字进行
close()
设置,无论
SO_LINGER
的值如何。该选项的目的是在连接关闭后接收(并丢弃)与连接关联的散乱数据,以免将它们意外传送到另一个套接字。
And a final guess which I ask to confirm: I'm allowed to read and write simultaneously, but N>1 concurrent writes is a data race and everything that I have to deal with it is a mutex.
send()
和
recv()
)都是线程安全的。但是,多个线程写入同一套接字会带来麻烦,因为单个调用的线程安全性不能保证多个调用之间的一致性。
关于c++ - Epoll零recv()和负(EAGAIN)send(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57813838/
关闭。这个问题需要details or clarity .它目前不接受答案。 想改进这个问题吗? 通过 editing this post 添加细节并澄清问题. 关闭 8 年前。 Improve t
美好的一天, 我正在用 VC++ 开发一个应用程序,它使用 UDP 协议(protocol)与 Windows XP 上的 winsock 进行通信。以前我已经能够假设该工具接收到的所有数据包都来自一
所以我需要从服务器向客户端接收一个 html 文件,该文件比缓冲区大所以我发送了几次。这就是为什么我在接收时有这个循环 while (i = recv(s, buf, TAM_BUFFER, 0))
我有几个关于 C 中的套接字库的问题。这是我将在问题中引用的代码片段。 char recv_buffer[3000]; recv(socket, recv_buffer, 3000, 0); 我如何决
当我的代码处于阻塞的 recv 调用中时,如果另一端重新启动,那么这一端的 recv 调用不会知道它,只会进入挂起状态。 如何避免这种情况? 最佳答案 默认情况下,如果连接的另一端在没有正确终止连接的
我有一个在平台上运行的 TCP 服务器,它从缓冲区读取字节并在一个发送调用中通过网络发送所有字节: send(sSocket.client_sock, base, frb_size, 0); frb_
假设以下代码(为了简单起见,我在这里省略了必要的错误处理): recv(sockfd, NULL, 0, MSG_PEEK); recv(sockfd, buff, bufflen, 0); 在那种情
我想用 ansible 安装 facebook osquery。 ubuntu的使用说明如下: sudo apt-key adv --keyserver keyserver.ubuntu.com --
我遇到了 recv() 和 send() winsock api 的问题。 Recv() 在接收最后一个数据包时挂起。 问题描述:- 系统 A 的应用正在通过非阻塞套接字写入数据,而系统 B 的应用正
我正在构建一个 TCP 应用程序,它使用换行符 \n 来分隔未知长度(但通常小于 64 字节)的消息。我正在寻找 this article非常有用。 是一次recv一个字符并检查它是否为换行符或r
我使用 epoll 实现 TCP 套接字通信来监视所有客户端事件,只有一个线程在一个 for 循环中处理所有客户端。每个套接字都是非阻塞的。 现在我遇到了一个问题,当客户端发送的数据超过MTU时,意味
在python中,方法是: socket.recv(bufsize[, flags]) 在C中,方法是: int recv( _In_ SOCKET s, _Out_ char *buf, _In_
如果我有一个套接字 s 会发生什么,它上面当前没有可用数据,它是一个阻塞套接字,我从两个套接字上调用 recv线程一次?其中一个线程会获取数据吗?双方都会得到吗?第二次调用 recv 会返回错误吗?
我有一个非常烦人的问题,我在其他论坛上发现了几次,但是找不到合适的解决方案。 问题是recv()在连接的最后几个字节上返回0。以下是一些背景信息。 两种(客户端/服务器)应用程序都在同一台计算机上运行
我正在使用 C 语言在 Unix 上编写客户端/服务器程序,使用发送/接收。我偶尔会从 recv 调用中遇到段错误。该行为不能完全重现;有时它会发生,有时程序会运行到完成。 知道这意味着什么吗? 最佳
我想 mock 套接字的recv函数并遇到麻烦。即使我没有必要,也要获取实际上连接套接字所需的错误。 这是所有相关代码: Class A: def __init__.py(self):
我已经编写了一个服务器-客户端程序,我想问一问:32位和64位操作系统之间recv()函数的行为是否有所不同。 我之所以这样问是因为我在64位笔记本电脑上同时运行服务器和客户端,并且一切正常。我这样调
我有许多设备需要从中获取状态更新。我只需要一个套接字对象,而我只需要 socket.recv() 来获取状态。放入单线程应用程序,不会出现问题: class Device: def recei
在 C 中,我希望读取页面的 html,但我希望保存数据的缓冲区是动态的。我知道我必须通过循环和使用 realloc 来执行此操作但我不太确定我将如何去做。假设我的套接字( sock )已经打开,请考
这个循环应该逐行从套接字中获取数据并将其放入缓冲区。出于某种原因,当没有新数据返回时, recv 返回它得到的最后几行。我能够通过注释掉第一个 recv 来阻止这个错误,但是我不知道下一行会有多长时间
我是一名优秀的程序员,十分优秀!