用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);
}
}
}