我做的是服务端Socket,各位高手先看看代码吧
ServerSocketChannel serverChannel = ServerSocketChannel.open();
serverChannel.socket().bind(new InetSocketAddress(CommonBean.getSocketPort()));
serverChannel.configureBlocking(false);
Selector acceptSelector = SelectorProvider.provider().openSelector();
SelectionKey acceptKey = serverChannel.register(acceptSelector, SelectionKey.OP_ACCEPT);
int keysAdded = 0;
int k = 0;
while ((keysAdded = acceptSelector.select(1000 * 60)) > 0) {
Set readyKeys = acceptSelector.selectedKeys();
Iterator i = readyKeys.iterator();
while (i.hasNext()) {
SelectionKey selectionkey = (SelectionKey) i.next();
i.remove();
if (selectionkey != null) {
new Thread(new SocketThread(selectionkey)).start();
}
}
}
public class SocketThread extends Thread {
public SocketThread(SelectionKey selectionkey) {
this.selectionkey = selectionkey;
}
public void run() {
try {
ServerSocketChannel nextReady = (ServerSocketChannel) selectionkey.channel();
socketChannel = nextReady.accept();
if (socketChannel != null){
socketLog.info("[ "+socketChannel.socket().getInetAddress().getHostAddress()+" ] Thread started....");
processRequest();
socketLog.info("[ "+socketChannel.socket().getInetAddress().getHostAddress()+" ] Thread ended...");
}
} catch (Exception e) {
socketLog.error(e.getMessage(), e);
}
}
private void processRequest() {
try {
while (true) {
ByteBuffer tempMsgID = ByteBuffer.allocate(4);
tempMsgID.clear();
socketChannel.read(tempMsgID);
tempMsgID.flip();
if (tempMsgID.limit() == 0) {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
socketChannel.socket().close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
我把服务端建立socket通讯的主要代码都摘取出来了,麻烦各位高手分析一下问题的原因以及解决的办法,我的问题如下:
一、我在前面已经设置了serverChannel.configureBlocking(false);为非阻塞模式,为什么当我调用socketChannel.read(tempMsgID);的时候,read依然用阻塞的方式去读取数据呢?
二、测试时候发现,如果客户端拔网线或者拔电源时,服务端不知道客户端退出,所以read就永远死在程序里了,当前的这个线程就一直存在了,我现在想设置read的timeout,比如说不管客户端异常退出还是由于其他原因,只要read超过3分钟,我就将当前这个socket关闭退出,在网上找了好久,没找到如何能设置socketChannel的timeout方法,不知道是我没找到,socketChannel就无法设置超时,如果无法设置超时,那么我的这个问题有没有别的解决办法呢?
三、我在网上查找socketChannel的timeout的方法时,发现socket可以设置超时,所以想到将socket从socketChannel中提取出来,用socket的方式进行读取,例如:socketChannel.socket().getinputstream();虽然说新版的NIO和旧版的纯socket相结合使用有点不伦不类,但是数据真的能正常收取,并且设置timeout也按时退出了,但是这种方式有新的问题,当我用20台客户端并发访问服务端的时候,运行一段时间就报too many open files的错误了,我检查程序了,我在最后的finally模块中,确实每次都将inputstream和socket全都close()了,但是依然解决不了too many open files异常,不知道该怎么办了。
希望NIO方面的高手来指点一下,NIO我接触的不多,现在这几个问题实在是没有能力解决了。