epoll模型有两种工作模式,ET和LT两种模式下都有一些细节值得注意,以下是一些思考:
 
一、ET模式下
Q1:调用accept时,到底TCP完成队列里有多少个已经建立好的连接?
这里又得分情况来说:
  • 没有连接。这种情况发生在TCP连接被客户端夭折,即在服务端调用accept之前客户端给出一个RST该RST导致刚刚建立好的连接从服务器端的TCP完成队列中被移出。源自berkeley的实现会在内核处理该事件,并不会将该事件通知给服务程序,如果套接口被设置为阻塞模式,就会导致accept函数被阻塞,程序挂起,一直要等到下一个连接到来,这也是为什么采用非阻塞的accept的原因;其他的实现通常会返回ECONNABORTED或EPROTO错误。

解决方法采用非阻塞的accept,在accept返回后处理ECONNABORTED、EPROTO、EINTR错误。

  • 一个以上的连接。一个连接很容易理解,多个连接的情况出现在有多个连接请求同时到达的情况,由于是边缘触发,epoll_wait只返回一次,然后调用accept处理一个请求这会导致TCP完成队列中依然存在连接未被处理。

解决办法:

1):将该套接口设置为非阻塞模式,然后将accept用while循环包住,处理完TCP完成队列中的所有连接再跳出循环。

2):将accept放入一个单独的线程中,这样还可以采用阻塞模式。

Q2:read函数应当如何处理?

read函数有可能不能够一次将内核缓冲的数据读完,由于采用的ET模式,epoll_wait不会因为内核缓冲区还有数据而继续读取。这就会导致内核数据不能及时、完全地读到服务程序。

解决办法将套接口设置为非阻塞,再用while循环包住read一直读到产生EAGAIN错误,采用非阻塞套接口的原因在于防止read被阻塞住。网上看见有的朋友说也可以采用阻塞套接口,判断read的返回值是否小于期望值,小于就证明数据读完,但是个人认为这里存在一个临界情况,比如内核缓冲有2048字节,期望读1024字节,读完第二次后read返回的是1024,等于期望值,于是再读,但此时内核已经没有数据,于是read被阻塞(自个的思考,不知有务否)。

Q3:写缓冲区什么时候可以导致epoll_wait函数返回可写状态?

个人对这个问题不是很清楚,按资料说法是该缓冲区从不可写变为可写则返回,那么该套接口刚创建的时候处于可写状态,是否会导致一直返回不了可写状态,也就是说第一次永远返回不了,因为没有任何调用会使该套接口从不可写变为可写。

另外,写的时候还有些什么要注意的么?

二、LT模式下

Q1:accept函数

accept函数同样存在连接被夭折的情况,和ET模式下类似。但这种模式下不会存在处理不完多个请求的情况。因为只要有连接存在TCP完成队列中,epoll_wait就会一直返回。

Q2:read函数

同样可以避免因为一次读不完内核缓冲区的数据的情况。

Q3:当内核写缓冲空闲时,可写状态会一直返回,如何处理?(这个曾是tencent的一个面试题)

A1:不将可写条件加入epoll集中,采用非阻塞I/O,有数据可写时,直接写,如果返回是EAGAIN,则将可写加入epoll集中,写完后移出。

通常都是写失败情况下,才会将写加入epoll中操作。

UNIX网络编程——epoll的 et,lt关注点的更多相关文章

  1. UNIX网络编程——epoll 的accept , read, write(重要)

    在一个非阻塞的socket上调用read/write函数,返回EAGAIN或者EWOULDBLOCK(注:EAGAIN就是EWOULDBLOCK). 从字面上看,意思是: EAGAIN: 再试一次 E ...

  2. UNIX网络编程——epoll 系列函数简介、与select、poll 的区别

    前面博客<<UNIX环境高级编程--epoll函数使用详解>>有关于epoll函数的讲解. 一.epoll 系列函数简介 #include <sys/epoll.h> ...

  3. unix网络编程 str_cli epoll 非阻塞版本

    unix网络编程 str_cli epoll 非阻塞版本 unix网络编程str_cli使用epoll实现讲了使用epoll配合阻塞io来实现str_cli,这个版本是配合非阻塞io. 可以看到采用非 ...

  4. unix网络编程str_cli使用epoll实现

    unix网络编程str_cli使用epoll实现 unix环境高级编程中也有这个函数,都是为了讲解IO多路转接.从本质上来看epoll就是一个改善了的select和poll,本质没发生任何变化,对于构 ...

  5. UNIX网络编程——并发服务器(TCP)

    在迭代服务器中,服务器只能处理一个客户端的请求,如何同时服务多个客户端呢?在未讲到select/poll/epoll等高级IO之前,比较老土的办法是使用fork来实现. 网络服务器通常用fork来同时 ...

  6. 《Unix 网络编程》14:高级 I/O 函数

    高级 I/O 函数 ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ★ ...

  7. UNIX网络编程——getsockname和getpeername函数

    UNIX网络编程--getsockname和getpeername函数   来源:网络转载   http://www.educity.cn/linux/1241293.html     这两个函数或者 ...

  8. 【LINUX/UNIX网络编程】之简单多线程服务器(多人群聊系统)

    RT,Linux下使用c实现的多线程服务器.这个真是简单的不能再简单的了,有写的不好的地方,还希望大神轻拍.(>﹏<) 本学期Linux.unix网络编程的第四个作业. 先上实验要求: [ ...

  9. 【LINUX/UNIX网络编程】之使用消息队列,信号量和命名管道实现的多进程服务器(多人群聊系统)

    RT,使用消息队列,信号量和命名管道实现的多人群聊系统. 本学期Linux.unix网络编程的第三个作业. 先上实验要求: 实验三  多进程服务器 [实验目的] 1.熟练掌握进程的创建与终止方法: 2 ...

随机推荐

  1. 【网络流】【BZOJ1001】狼抓兔子

    继续网络流的学习.... 题意简析:就是给你张图,叫你求最小割. 解题思路:最小割=最大流,按题意见图跑一次就好了. 附代码: #include<cstdio> #include<i ...

  2. 【HDU 1576】 A/B

    Problem Description 要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1).   Input 数据的 ...

  3. C++11的原子量与内存序浅析

    一.多线程下共享变量的问题 在多线程编程中经常需要在不同线程之间共享一些变量,然而对于共享变量操作却经常造成一些莫名奇妙的错误,除非老老实实加锁对访问保护,否则经常出现一些(看起来)匪夷所思的情况.比 ...

  4. HashMap实现原理和源码解析

    哈希表(hash table)也叫散列表,是一种非常重要的数据结构.许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表,本文会对java集合框架中的对应实现HashMap的 ...

  5. Genymotion配置遇到的坑

    1.Genymotion 无法Add下来 解决: ①首先打开Genymotion,的Settings然后找到VirtualBox,复制链接,在本地找到文件夹,然后返回上一层找到ova文件夹进入, ②然 ...

  6. HTTP请求分析工具Fiddler

    主要用于分析http头信息和响应头信息,以及具体的post数据和响应数据,可以监测电脑上http请求.

  7. c++类的声明

    就像函数的声明与定义分离一样,我们也可以仅声明类而暂时不定义类: class ClassName;//ClassName类的声明 这种声明有时被称作前向声明 对于一个类来说,我们创建它的对象之前该类必 ...

  8. popen() 使用举例 (转载)

    函数原型: #include "stdio.h" FILE *popen( const char* command, const char* mode ) 参数说明: comman ...

  9. MongoDB 自动增长

    MongoDB 没有像 SQL 一样有自动增长的功能, MongoDB 的 _id 是系统自动生成的12字节唯一标识. 但在某些情况下,我们可能需要实现 ObjectId 自动增长功能. 由于 Mon ...

  10. AbstractQueuedSynchronizer源码解读

    1. 背景 AQS(java.util.concurrent.locks.AbstractQueuedSynchronizer)是Doug Lea大师创作的用来构建锁或者其他同步组件(信号量.事件等) ...