epoll的EPOLLOUT事件

发布于 2022-08-31 20:17:15 字数 724 浏览 14 评论 0

文档上说epoll监听的描述符可写的时候会触发EPOLLOUT事件,

可是我想知道在接受到EPOLLOUT后,调用write还有限制吗,比如write过大的数据会不会还是返回EAGAIN

想像这样的场景

  • 服务器收到客户端的请求,要获取一张图片。
  • 服务器读取该图片,保存为字节数组(**char***)
  • 然后调用write欲将数据写入套接字,却返回EAGAIN
  • epoll_ctl为套接字添加EPOLLOUT的事件监听

    那么问题来了,当**EPOLLOUT**事件发生时,往该套接字写该图片的数据,是否能成功
    

服务器使用C语言开发。不过我想其他语言的epoll都是从C语言绑定过去的,原理应该一样。

这里有点要注意的是,第一次write失败是因为数据量太大,如果write数据少一点是可以成功的。(至少从经验看是如此)那么当EPOLLOUT触发时能保证write一张大图片的数据会成功吗。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一笔一画续写前缘 2022-09-07 20:17:15

socket没关闭,随时可以往里面写数据吧,写如果打会分片传输给client的。

謸气贵蔟 2022-09-07 20:17:15
/*
 * Packs up the buf and write to socket in non-blocking way
 * If all data is writen, return 1
 * If only part of data is writen, return 0, to be continue next time
 * If error occurs, return -1
 * 
 * Note, if j_socket_write() returns 0, then you can call it with NULL in buf next time, until all data is writen
 */
int j_socket_write(JSocket * jsock, const void *buf, guint32 count)
{
    guint32 size = j_socket_wdata_length(jsock);
    if (size == 0) {
        /* new data to write */
        if (buf == NULL) {
            return 1;           /* no data? must be a mistake */
        }
        gchar *len = pack_length4(count);
        j_socket_wdata_append(jsock, len, 4);
        j_socket_wdata_append(jsock, buf, count);
        g_free(len);
        size = j_socket_wdata_length(jsock);
    }

    gint n;
    count = size>4096?4096:size;

    while(size>0){  /* writes segmentation */
        n = j_socket_write_raw(jsock, j_socket_wdata(jsock), count);
        if(n<0){
            if(errno==EAGAIN){
                return 0;
            }
            return -1;  /* It's a real error */
        }
        j_socket_wdata_pop(jsock,n);
        size = j_socket_wdata_length(jsock);
        count = size>4096?4096:size;
    }
    return 1;
}

@我是宅男小何 刚好提醒了我,其实就算整块数据很大,也不一定要调用一次write就全部写入。
上面代码,将超过4096的数据分片发送,如果阻塞,则返回等待下一次调用。

这段代码还没有测试过,基本这个逻辑

以往的大感动 2022-09-07 20:17:15
如果是水平触发的情况下。EPOLL触发时,代表套接字是可写的,也就是说,你可以向套接字写东西。
如果你一次写入的数据太大,占满了套接字的缓冲区,那么就有两种情况。
  1. 套接字是阻塞的:这时write并不会返回,write会阻塞在那里不断地尝试去写,直到写完数据后返回成功。
  2. 套接字是非阻塞的:这时把套接字的缓冲区写满过后,write就会返回实际写入套接字的字节数。

你说的返回EAGAIN是在非阻塞环境下,尝试用阻塞的操作不断去写就会返回这种errno。所以在触发EPOLLOUT的情况下是不会出现这种错误的。但是我写代码是一般都会检查EAGAIN还有EWOULDBLOCK这两种错误,然后忽略掉。

向地狱狂奔 2022-09-07 20:17:15

在epoll的ET模式下,正确的读写方式为:
读:只要可读,就一直读,直到返回0,或者 errno = EAGAIN
写:只要可写,就一直写,直到数据发送完,或者 errno = EAGAIN 下次再写

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文