Selector可以拥有无限制个连接,当然在硬件承受范围之内。通过不断的轮询selectionKey查看当前的可操作的通道,也可以在注册到selector上面。
点击查看大图
也可以保存通道做一个点对点的聊天播放器。规定消息的格式,比如lisi:nihao 给李四发送消息nihao。
//保存姓名和网络地址(host:port)的一一对应关系
Map<String, SocketAddress> nameAddress = new ConcurrentHashMap<>();
//保存网络地址(host:port)和channel的一一对应关系
Map<SocketAddress, SocketChannel> addressChannel = new ConcurrentHashMap<>();
注册客户端
SocketAddress sa = sc.getRemoteAddress();
nameAddress.put(username, sa);
addressChannel.put(sa, sc);
System.out.println("进入聊天室的是:[" + username + "]-:地址" + sc.getRemoteAddress());
发送给指定的人
String[] users = username.split(":");
if(users.length == 3) {
SocketAddress address = nameAddress.get(users[1]);
if (address != null) {
SocketChannel socketChannel = addressChannel.get(address);
if (socketChannel != null) {
socketChannel.write(UTF8Utils.encode(users[0] + "说:【" + users[2] + "】"));
} else {
sc.write(UTF8Utils.encode("他不在线。。"));
}
} else {
sc.write(UTF8Utils.encode("他不在线。。"));
}
}else{
sc.write(UTF8Utils.encode("输入信息无效。。"));
}
检测到客户端失败时,可以取消selectionKey
if (sk.isValid() && sk.isReadable()) {
SocketChannel sc = null;
try {
sc = (SocketChannel) sk.channel();
//用来处理连接内的内容
parse(sc);
} catch (IOException e) {
addressChannel.remove(sc.getRemoteAddress());
nameAddress.remove(getKey(nameAddress, sc.getRemoteAddress()));
sk.cancel();
System.out.println("e 3" + e.getMessage());
}
}