首页 > 解决方案 > 具有非阻塞套接字的 Kqueue/epoll (FreeBSD/Linux):写入/发送/发送后何时可以释放缓冲内存?

问题描述

我有使用 kqueue/epoll (FreeBSD/Linux) 的非阻塞套接字(TCP 或 UPD 套接字)。当我想将字节传输到另一端时,我可以使用 write/send/sendto。它们每个都使用 char* 缓冲区进行传输,但我不明白在调用 write/send/sendto 后何时必须释放缓冲区内存。

  1. 如果 write/send/sendto 返回接受的字节数并且这个数字等于缓冲区大小,我可以立即释放缓冲区内存是否正确?或者我必须等待 EVFILT_WRITE (kqueue) 或 EPOLLOUT (Linux) 事件来释放缓冲区内存?
  2. 如果 write/send/sendto 返回接受的字节数并且这个数字不等于缓冲区大小,我只能立即释放接受的字节,我必须等待 EVFILT_WRITE (kqueue) 或 EPOLLOUT (Linux) 事件继续传输不接受的字节和下一个字节?或者我必须等待 EVFILT_WRITE (kqueue) 或 EPOLLOUT (Linux) 事件来释放缓冲区内存并传输下一个字节?
  3. 如果 write/send/send 是否返回 EAGAIN (kqueue) 或 EAGAIN || EWOULDBLOCK (Linux),我无法释放缓冲区内存,我必须等待 EVFILT_WRITE (kqueue) 或 EPOLLOUT (Linux) 事件来重新传输相同的字节?

标签: linuxfreebsdnonblockingepollkqueue

解决方案


尽管您使用的是非阻塞套接字,但 write/send/sendto 调用仍然是同步的。这意味着您可以在缓冲区告诉您调用成功后立即释放它。

1.是的

当 write/send/sendto 返回完整的缓冲区大小时,表示缓冲区的全部内容已复制到套接字发送缓冲区,您可以立即释放缓冲区。

2.是的

当 write/send/sendto 返回部分大小时,您应该等待下一个可写事件发送剩余字节。

3.是的

EAGAIN 或 EWOULDBLOCK 表示写入非阻塞套接字时写入缓冲区已满。您应该再次发送这些字节。


推荐阅读