Java NIO的一些总结

  1.  channel在linux系统中也是一种文件,

 Channels are analogous to "file descriptors" found in Unix-like operating systems.

故一个Selector管理的channel也有数目限制, 若超过限制会报如下错误:

java.io.IOException: Too many open files
	at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
	at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:241)


2. 使用java IO(即使用socket.getOutputStream())往服务端写数据时,若发生了网络超时, 仍能成功写入,只不过是写到了OS的Send-Q中。如下所示:

$ netstat -nat
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State    
......
$ netstat -nat|grep 9001
tcp6      30     60 127.0.0.1:57256         127.0.0.1:9001          ESTABLISHED
$ netstat -nat|grep 9001 #第三列send_q由60增加为70了
tcp6      30     70 127.0.0.1:57256         127.0.0.1:9001          ESTABLISHED
...
$ netstat -nat|grep 9001
tcp6      30    520 127.0.0.1:57256         127.0.0.1:9001          ESTABLISHED
#等网络恢复正常后 会被服务端一次性接收
$ netstat -nat|grep 9001
tcp6     615      0 127.0.0.1:57256         127.0.0.1:9001          ESTABLISHED

等网络恢复正常时, 会被服务端一次性接收到之前客户端超时期间累积的数据。这种情况下没有办法设置写超时。

但若使用NIO的话, 注册了socketChannel写事件的话,如下所示:

scChannel.register(selector, SelectionKey.OP_WRITE);

 若网络超时的话, selector是不会选择该channel的,若客户端仅有该channel的话,会阻塞在selector.select()中,如下所示:

sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79)
sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:87)
   - locked sun.nio.ch.Util$2@e4f15c3
   - locked java.util.Collections$UnmodifiableSet@6a1dbc8b
   - locked sun.nio.ch.EPollSelectorImpl@4645801a
sun.nio.ch.SelectorImpl.select(SelectorImpl.java:98)
sun.nio.ch.SelectorImpl.select(SelectorImpl.java:102)

故也就不会往服务端写数据了。

你可能感兴趣的:(nio)