nio 老是堵塞 附上例子 求教高手
用nio写了个服务器的程序 ,少些可以,客户多了以后, 老是堵塞 ,发现程序里面某个key可写的时候 客户端没反应
后来在每次服务器对key对应的channel read后考虑实际需要,对每个刚读取过的key.interestOps()还是堵塞
有个疑问 什么时候key.isWritable()返回真
public class ChatServer {
private int port = 13;
private Selector selector;
private ServerSocketChannel ssc;
private ServerSocket server;
private InetSocketAddress address;
private HashMap <String, SelectionKey> userlist = new HashMap <String, SelectionKey> ();
private List alluser = new ArrayList <String> ();
private HashMap <String, StringBuilder> messagelist = new HashMap <String, StringBuilder> ();
// SelectionKey> ();
public ChatServer() {
// initServer
// this.sc = sc;
try {
ssc = ServerSocketChannel.open();
server = ssc.socket();
address = new InetSocketAddress(port);
server.bind(address);
selector = Selector.open();
ssc.configureBlocking(false);
ssc.register(selector, SelectionKey.OP_ACCEPT);
System.out.println( "Listening the port 13... ");
} catch (IOException ex) {
ex.printStackTrace();
System.exit(-1);
}
}
public void sendmessage(SelectionKey sk, StringBuilder message) {
try {
SocketChannel sc = (SocketChannel) sk.channel();
ByteBuffer tbuffer = ByteBuffer.wrap(message.toString().getBytes());
while (tbuffer.hasRemaining() & sc.write(tbuffer) != -1)
;
} catch (Exception e) {
e.printStackTrace();// TODO: handle exception
}
}
public void startServer() throws IOException {
while (true) {
int i = selector.select();
Iterator keys = selector.selectedKeys().iterator();
while (keys.hasNext()) {
SelectionKey key = (SelectionKey) keys.next();
keys.remove();
try {
if (key.isAcceptable()) {
ServerSocketChannel ssc = (ServerSocketChannel) key
.channel();
SocketChannel channel = ssc.accept();// return null
System.out.println(channel + " has accepted ");
channel.configureBlocking(false);
SelectionKey clientKey = channel.register(selector,
SelectionKey.OP_READ);
}
if (key.isWritable()) {
if (alluser.size() > 0) {
String user = (String) key.attachment();
StringBuilder message = messagelist.get(user);
if (!message.toString().equals( " ")) {
sendmessage(key, message);
System.out.println( "write: " + user + " "
+ message);
}
messagelist.remove(user);
messagelist.put(user, new StringBuilder( " "));
}
// key.interestOps(SelectionKey.OP_READ|SelectionKey.OP_WRITE);
}
if (key.isReadable()) {
SocketChannel channel = (SocketChannel) key.channel();
ByteBuffer buffer = ByteBuffer.allocate(50);
channel.read(buffer);
buffer.flip();
String checkBuffer = this.decode(buffer);
System.out.println( "read: " + checkBuffer);
if (checkBuffer.startsWith( "login ")) {
String user = checkBuffer.substring(6, checkBuffer
.length());
System.out.println( "user: " + user + " login ");
String username = checkBuffer.substring(6,
checkBuffer.length());
key.attach(user);
userlist.put(user, key);
messagelist.put(user, new StringBuilder( "welcome "
+ user));
alluser.add(user);
key.interestOps(SelectionKey.OP_WRITE
| SelectionKey.OP_READ);
} else if (checkBuffer.startsWith( "chat ")) {
String message1 = checkBuffer.substring(5);
String reveiver = message1.substring(0, message1
.indexOf( " "));
String message = message1.substring(message1
.indexOf( " ") + 1, message1.indexOf( "| "));
String sender = message1.substring(message1
.indexOf( "| ") + 1, message1.length());
String message2 = "[you-> " + reveiver + ": "
+ message + "]\n ";
message = "[ " + sender + "-> you: " + message
+ "]\n ";
messagelist.get(reveiver).append(message);
messagelist.get(sender).append(message2);
// key.interestOps(SelectionKey.OP_WRITE);
System.out.println( "read: " + message);
} else if (checkBuffer.startsWith( "list ")) {
String reveiver = checkBuffer.substring(checkBuffer
.indexOf( "| ") + 1, checkBuffer.length());
StringBuilder list = new StringBuilder( " ");
Iterator <String> it = alluser.iterator();
while (it.hasNext()) {
list.append( "[ " + it.next() + "]\n ");
}
list.append( "\n ");
messagelist.get(reveiver).append(list);
// key.interestOps(SelectionKey.OP_WRITE);
} else if (checkBuffer.startsWith( "broadcast ")) {
String broadcast = " ";
String message = checkBuffer
.substring(checkBuffer.indexOf( " ") + 1,
checkBuffer.indexOf( "| "));
String user = checkBuffer.substring(checkBuffer
.indexOf( "| ") + 1, checkBuffer.length());
broadcast = "[world( " + user + "): " + message
+ "]\n ";
Iterator <String> it = alluser.iterator();
while (it.hasNext()) {
messagelist.get(it.next()).append(broadcast);
}
// key.interestOps(SelectionKey.OP_WRITE);
System.out.println( "read: " + broadcast);
} else if (checkBuffer.startsWith( "logout ")) {
String broadcast = " ";
String user = checkBuffer.substring(7, checkBuffer
.length());
// sc.logout(user);
messagelist.remove(user);
userlist.remove(user);
String message = " ";
message = "[ " + user + " see you next time ] ";
System.out.println( "read: " + message);
SocketChannel sc = (SocketChannel) key.channel();
ByteBuffer tbuffer = ByteBuffer.wrap(message
.getBytes());
while (tbuffer.hasRemaining()
& sc.write(tbuffer) != -1)
;
key.cancel();
} else {
String message = checkBuffer.substring(0,
checkBuffer.indexOf( "| "));
message = "[unknown command ' " + message + " '] ";
String reveiver = checkBuffer.substring(checkBuffer
.indexOf( "| ") + 1, checkBuffer.length());
messagelist.get(reveiver).append(message);
System.out.println( "write: " + message);
}
}
} catch (IOException ex) {
key.cancel();
try {
key.channel().close();
} catch (IOException cex) {
}
}
}
}
}
public String decode(ByteBuffer buffer) {
Charset charset = null;
CharsetDecoder decoder = null;
CharBuffer charBuffer = null;
try {
charset = Charset.forName( "gb2312 ");
decoder = charset.newDecoder();
charBuffer = decoder.decode(buffer);
return charBuffer.toString();
} catch (Exception ex) {
ex.printStackTrace();
return " ";
}
}
public static void main(String[] args) {
ChatServer cs = new ChatServer();
try {
// st.start();
cs.startServer();
} catch (IOException ex) {
ex.printStackTrace();
System.exit(-1);
}
}
}
------解决方案--------------------
不是很清楚,不过还是帮你顶