服务器开发问题-EPOLLIN、EPOLLOUT触发情况

一、EPOLLIN、EPOLLOUT

1.0 缓冲区

1. 缓冲区机制

在网络通信中,每个套接字都有两个缓冲区:

  • 发送缓冲区:存储待发送的数据,位于发送方
  • 接受缓冲区:存储接受到的数据,位于接收方

对于TCP连接,数据发送过程如下:

  1. 应用程序将数据写入发送缓冲区
  2. TCP协议栈从发送缓冲区取出数据,通过网络发送给接收方
  3. 接收方的TCP协议栈接受数据(由OS完成),并存在接受缓冲区中
  4. 应用程序从接受缓冲区中读取数据

2. 事件和缓冲区关系

EPOLLOUT事件的触发调试是本地发送缓冲区有空间可用。原因:

  1. 操作系统对发送缓冲区的管理
    • 本地资源的管理: 操作系统直接管理每个套接字的发送缓冲区。通过 EPOLLOUT 事件,操作系统通知应用程序本地发送缓冲区是否有空间可以写入。
    • 发送缓冲区的状态易于监控: 操作系统实时跟踪和管理发送缓冲区的状态。当发送缓冲区有空间时,EPOLLOUT 事件就会被触发,通知应用程序可以继续写入数据。
  2. 客户端接收缓冲区的状态不可直接监控
    • 远程资源的不可控性: 客户端的接收缓冲区是位于远程系统中的资源,服务器无法直接监控和管理它的状态。
    • TCP 协议的流量控制机制: TCP 协议有内置的流量控制机制,接收方会通过滑动窗口(sliding window)机制告知发送方接收缓冲区的可用大小。如果接收缓冲区满了,接收方会减少窗口大小或完全关闭窗口,通知发送方停止发送数据。这是 TCP 协议层面处理的,不需要应用层直接监控接收方的缓冲区状态。

EPOLLIN事件同理。

1.1 触发条件

  1. EPOLLIN:当文件描述符上有数据可读时触发。通常在以下情况:
    • 有新的客户端连接到服务器(对于监听套接字)
    • 套接字上有新数据可读
    • 套接字接收到EOF,意味着连接被关闭或终止
  2. EPOLLOUT: 当文件描述符可以写数据时触发。通常:
    • 套接字缓冲区有可用的空间可写入数据
    • 首次连接建立后,如果套接字的连接操作(connect)完成,触发EPOLLOUT事件
    • 在非阻塞模式下,当先前的发送操作因缓冲区满而失败后,一旦缓冲区重新可用,会触发

1.2 EPOLLOUT的具体场景

  1. 初始连接完成

    当你使用非阻塞模式调用connect函数来连接远程主机,如果connect返回-1并且errnoEINPROGRESS,这意味着连接正在进行中。此时,可以通过监视 EPOLLOUT 事件来检测连接何时完成。当连接完成时,套接字会触发 EPOLLOUT 事件。

  2. 写缓冲区可用

    在非阻塞套接字上,如果你之前的 send 操作因为写缓冲区已满(EAGAINEWOULDBLOCK 错误)而无法完成,你可以监视 EPOLLOUT 事件。当缓冲区有空间可写时,EPOLLOUT 事件会被触发,这时你可以继续写数据。

1.3 客户端断开的情况

  1. 客户端主动断开连接

    • 如果客户端主动断开连接,服务器端的套接字会触发 EPOLLIN 事件。当你在服务器端调用 recv 函数时,会收到 0 字节,这表示对方已经关闭了连接。
    • EPOLLOUT:通常不会因为客户端主动断开连接而直接触发。客户端断开连接后,服务器端的套接字上往往会出现可读事件(EPOLLIN),提示你连接已经关闭。
  2. 客户端意外断开连接

    • 服务器端仍然触发EPOLLIN事件。但是recv函数返回-1,并且errno不是EAGAINEWOULDBLOCK
      这表示发生了错误。此时则需要根据错误码处理连接错误。
  3. 服务器发送数据时发现连接关闭:

    • 如果服务器尝试向已经断开的连接发送数据,这可能会导致 send 函数返回 -1,并设置 errnoEPIPEECONNRESET。这时,你可以通过处理错误来得知连接已经关闭,但这并不是通过 EPOLLOUT 事件检测到的。
  4. 注意事项

    • EPOLLOUT 触发频率:

      EPOLLOUT 事件非常频繁地触发,因为只要有可用的写缓冲区空间,它就会触发。因此,通常在你需要发送数据时才添加对 EPOLLOUT 事件的监控,并在写入操作完成后尽快移除该监控,以避免处理过多的无效事件。

    • 处理连接断开的方式:

      对于服务器,检测客户端断开的最可靠方式是通过 EPOLLIN 事件,接收 0 字节的数据。不要依赖 EPOLLOUT 来判断连接状态,因为它主要用于管理写操作的可用性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值