socket在epoll两种工作模式下注册事件的工作原理是怎样的?
1.LT是epoll缺省的工作方式,同时支持blocking和nonblocking socket
通常的NIO framework均要把socket设置为nonblocking,blocking是用在什么场景下使用?
2.ET仅支持nonblocking socket,为什么?
java中的selector对于linux而言底层实现为epoll的LT模式,为什么不提供ET模式?
@乌龟壳,@中山野鬼
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
bingo
@乌龟壳 ,对于ET模式不能设置阻塞,是由于很大程度上可能是因为在改模式下需要处理读到空,写到满;如果是阻塞的,这个时候导致线程阻塞在读写而不是epoll_wait了,进而无法处理其他socket,标准答案应该加上你下面的部分
blocking 和时序有关。nonblocking强调并发。 java的不懂。哈。
java 实现NIO也是需要底层系统支持的,但是它愿意支持多少,对于java程序员来说才能用多少
回复
性能和底层有关系,但JAVA的API到底是LT还是ET是java自己实现的,就算java底层用ET(其实甚至不一定是epoll,iocp没有et这个概念),java照样可以实现成LT。java有自己的缓冲区,这个API完全可以独立实现逻辑。
java里怎么做,是java的API实现的逻辑,和epoll不是一个层面的事情。
补充,ET为了把缓冲区读完,使用nonbloking可以做到在缓冲区空的时候返回一个缓冲区空的标志EAGAIN,如果使用blocking就在缓冲区空的时候直接阻塞了。后者并不是我们期望的执行效果,严格的异步程序只有调用epoll等待事件时允许阻塞,其它时候都要尽可能高效地使用CPU而不能作IO等待等。
EAGAIN The file descriptor fd refers to a file other than a socket and has been marked nonblocking (O_NONBLOCK), and the read would block.
但是如果我们可以得到缓冲区的实际大小,那用blocking严格只读取缓冲区大小的数据也是不会阻塞的,这个API没接触过,应该有,不过没必要这样去做,对性能是一种浪费。
写也是这样,以此类推。
blocking socket也是可以注册LT 模式下epoll的
第一个问题是阻塞和非阻塞网络编程的应用场景吧,前者的优势是简单方便好控制,转载下:
"阻塞模式,常见的通信模型为多线程模型,服务端accept之后,对每个socket创建一个线程去recv。逻辑上简单,适用于并发量小(客户端数目少),连续传输大数据量的情况下,比如文件服务器。还有就是在客户端recv服务器消息的时候也经常用,因为客户端就一个socket,用阻塞模式不影响效率,而且编程逻辑上要简单得多。
非阻塞模式,常见的通信模型为select模型和IOCP模型。适用于高并发,数据量小的情况,比如聊天室。客户端多的情况下,如果采用阻塞模式,需要开很多线程,影响效率。另外,客户端一般不采用非阻塞模式。"
所以java的意思是如果你用到性能要求这么高情况,臣妾做不到,你换c去吧
2. 主要是因为性能效率没有相差很大的情况下, 使用edge-trigger比level-trigger逻辑更复杂,出错概率更高,编程要求也高。
回答的很棒
我的理解是,blocking和nonblocking和epoll是没有关系的。
epoll提供的是对socket收发缓冲区状态变更的通知,可读、可写、异常、已连接等的通知事件。
blocking和nonblocking是针对readwrite等函数在缓冲区满后,是否阻塞等待缓冲区有空间再执行下去的配置。
LT和ET只是通知方式不同,LT只要状态处于程序所关心的状态(可读,可写等),就发出通知。ET是只有状态发生变化后(接收缓冲区增加了数据,发送缓冲区减少了数据等)才通知。
所以写LT的程序,可以不一次性把缓冲区都处理完成,剩下的内容可以等下一轮事件循环处理,但写ET的程序就必须一次性把缓冲区的数据都处理完,不然下次只要缓冲区不变化就不通知,这样有可能有些数据就没有来得及处理。
例如缓冲区有数据:012345
使用LT处理:01—23—45,“—”代表下一次事件循环
错误使用ET:01—停住了,除非缓冲区又来了67
正确使用ET:012345—下一次通知