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)
故也就不会往服务端写数据了。