刚刚尝试用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();
}
}
问题是这样的:服务器实现的是一个多路复用服务器,代码如下,当有一个客户端连接并向服务器发送信息后(只有一个),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();
}
}
从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)