NIO中SelectionKey的OP_WRITE

纯洁袜子 2015-09-17 10:55:18
SelectionKey中的OP_WRITE是给感兴趣的键注册一个写事件,然后就可以往客户端写入。
但是测试发现就算我不注册写事件依然可以往客户端写东西,并没有什么问题,我完全可以在我读取到东西之后,直接往客户端写东西。
何必多此一举注册一个事件,让通道写准备就绪,然后再写入。
SelectionKey中的OP_WRITE这个事件到底派什么用?
...全文
439 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
纯洁袜子 2015-09-22
  • 打赏
  • 举报
回复
引用 5 楼 yanical 的回复:
[quote=引用 3 楼 zyb112211 的回复:] 我客户端异常断开之后(比如网络断开),write方法还是会写(线程,隔5秒往客户端写),但是好像是往缓存区写,当客户端连接上来之后(网络恢复),会把之前写的东西一次性发给客户端。 而且当客户端异常断开一段时间之后,通道就会抛出ClosedChannelException 这个错误,关闭的通道。 什么情况下会写不进去呢? 注册OP_WRITE之后是什么操作?是不是还是往客户端写?这不是一样么?
还可以试试,客户端你不要接受数据(不要read),服务器疯狂write,慢慢把所有缓冲都填满。这样服务器应该就写不进了。试试吧,我没试过。[/quote]写不进去倒是测出来了。。 然后当write返回0的时候,我给他注册一个OP_WRITE事件,并唤醒selector,跳出while循环。 然后在写事件里继续往里面写?
纯洁袜子 2015-09-18
  • 打赏
  • 举报
回复
我客户端异常断开之后(比如网络断开),write方法还是会写(线程,隔5秒往客户端写),但是好像是往缓存区写,当客户端连接上来之后(网络恢复),会把之前写的东西一次性发给客户端。 而且当客户端异常断开一段时间之后,通道就会抛出ClosedChannelException 这个错误,关闭的通道。 什么情况下会写不进去呢? 注册OP_WRITE之后是什么操作?是不是还是往客户端写?这不是一样么?
纯洁袜子 2015-09-18
  • 打赏
  • 举报
回复
引用 1 楼 yanical 的回复:
好吧,这是我的理解。 你调用写,可以调用,但是不见得可以写进去,假设你用非阻塞写,你可能只能写一部分甚至没有写进任何数据。能写多少数据受内核缓冲区的影响,必须等缓冲区原有数据已经被发出去了后,你要写的数据才能被填进缓冲区,也就是才能被写入。 所以,如果你只写了一部分数据进去,那什么时候还能再调用写呢?你可以不停的retry,直到写完,这样会浪费CPU周期,更好的解决方法就是注册OP_WRITE让内核告诉你,可以写数据了。
什么情况下会写不进去?注册OP_WRITE之后有什么作用么? 我之前测了好几种情况都没测出来会写不进去
yanical 2015-09-18
  • 打赏
  • 举报
回复
引用 3 楼 zyb112211 的回复:
我客户端异常断开之后(比如网络断开),write方法还是会写(线程,隔5秒往客户端写),但是好像是往缓存区写,当客户端连接上来之后(网络恢复),会把之前写的东西一次性发给客户端。 而且当客户端异常断开一段时间之后,通道就会抛出ClosedChannelException 这个错误,关闭的通道。 什么情况下会写不进去呢? 注册OP_WRITE之后是什么操作?是不是还是往客户端写?这不是一样么?
还可以试试,客户端你不要接受数据(不要read),服务器疯狂write,慢慢把所有缓冲都填满。这样服务器应该就写不进了。试试吧,我没试过。
yanical 2015-09-18
  • 打赏
  • 举报
回复
引用 3 楼 zyb112211 的回复:
我客户端异常断开之后(比如网络断开),write方法还是会写(线程,隔5秒往客户端写),但是好像是往缓存区写,当客户端连接上来之后(网络恢复),会把之前写的东西一次性发给客户端。 而且当客户端异常断开一段时间之后,通道就会抛出ClosedChannelException 这个错误,关闭的通道。 什么情况下会写不进去呢? 注册OP_WRITE之后是什么操作?是不是还是往客户端写?这不是一样么?
操作系统的缓冲区满了就写不进去了。这个看起来不大好测试,呵呵。如果你用你的断开网络方法测试,你用一个死循环(不要隔五秒)疯狂调用write方法,每次都要输出数据被写入了多少。然后拔网线,看一下你能不能成功写入。 提醒一下,write方法返回不代表写入成功了,要看write返回的int才能知道写入了多少数据。
yanical 2015-09-17
  • 打赏
  • 举报
回复 1
好吧,这是我的理解。 你调用写,可以调用,但是不见得可以写进去,假设你用非阻塞写,你可能只能写一部分甚至没有写进任何数据。能写多少数据受内核缓冲区的影响,必须等缓冲区原有数据已经被发出去了后,你要写的数据才能被填进缓冲区,也就是才能被写入。 所以,如果你只写了一部分数据进去,那什么时候还能再调用写呢?你可以不停的retry,直到写完,这样会浪费CPU周期,更好的解决方法就是注册OP_WRITE让内核告诉你,可以写数据了。

67,513

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧