刚刚尝试用nio库编写一个CS结构的小程序,结果碰到奇怪的问题,希望能有高手指点一下,不胜感激!
问题是这样的:服务器实现的是一个多路复用服务器,代码如下,当有一个客户端连接并向服务器发送信息后(只有一个),select()不断的返回1,并且接收的SelectionKey是Readable的!
不知道到底是哪里弄错了?
源代码如下:
服务器的代码:
public class Server {

Selector selector;
static long timeout = 5000; // 5 seconds
static int port = 4000;

public Server() throws IOException {
init();
}
public void run() throws IOException{

while(true) {
int num = selector.select(timeout); // 问题出现在这里
System.out.println(num);
if(num != 0) {
Set set = selector.selectedKeys();
System.out.println("set size:" + set.size());
Iterator it = set.iterator();

while(it.hasNext()) {
SelectionKey key = (SelectionKey)it.next();

if(key.isAcceptable()) {
accept((ServerSocketChannel)key.channel());
} else if(key.isReadable()) {
readFrom((SocketChannel)key.channel());
} else if (key.isWritable()) {
writeTo((SocketChannel)key.channel());
} else {
// ...

} //$ if(key.isAcceptable()) end

it.remove();
} //$ while(it.hasNext()) end
} //$ if(num != 0) end

// 清除无效连接
// clear();

} //$ while(true) end
}

/**
 * 初始化服务器。
 * @throws IOException 
 */
private void init() throws IOException {
// create server socket
ServerSocketChannel server = ServerSocketChannel.open();
server.socket().bind(new InetSocketAddress(port));
server.configureBlocking(false);

// create selector
selector = Selector.open();
server.register(selector, SelectionKey.OP_ACCEPT);

// init others
}

/**
 * 处理连接socket的请求
 * @param socket 服务器socket
 * @throws IOException 
 */
protected void accept(ServerSocketChannel serverSocket) throws IOException {
SocketChannel socket = serverSocket.accept();
socket.configureBlocking(false);
SingleSocket ss = new SingleSocket(socket);
sockets.addElement(ss);
if(map.put(socket, ss) != null) {
System.out.println("There is a socket connect twist!" + socket);
}
socket.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE);
}

/**
 * 从socket读取数据
 * @param socket 有数据传来的socket
 * @throws IOException 
 */
protected void readFrom(SocketChannel socket) throws IOException {
// ...
}

/**
 * 写数据到socket上
 * @param socket 目标socket
 */
protected void writeTo(SocketChannel socket) {
// ...
}

/**
 * 清除超时连接
 * @throws IOException 
 * @throws IOException 
 */
protected void clear() throws IOException {

}

public static void main(String[] args) throws IOException {
new Server().run();
}
}

解决方案 »

  1.   

    同时还有一个问题,我想可能和上面说的问题有联系:
    从SocketChannel读数据到ByteBuffer竟然出现异常,异常报告如下:Exception in thread "main" java.io.IOException: 远程主机强迫关闭了一个现有的连接。
    at sun.nio.ch.SocketDispatcher.read0(Native Method)
    at sun.nio.ch.SocketDispatcher.read(Unknown Source)
    at sun.nio.ch.IOUtil.readIntoNativeBuffer(Unknown Source)
    at sun.nio.ch.IOUtil.read(Unknown Source)
    at sun.nio.ch.SocketChannelImpl.read(Unknown Source)