这几天在学习nio相关知识。实现了一个简单的多人聊天程序。
服务端代码;
1 import java.io.IOException; 2 import java.net.InetSocketAddress; 3 import java.nio.ByteBuffer; 4 import java.nio.channels.*; 5 import java.nio.charset.Charset; 6 import java.util.*; 7 8 /** 9 * @ClassName CharRoomServer 10 * @Description TODO 11 * @Author hufeng8 12 * @Date 2018/8/3 14:39 13 * @Version 1.0 14 */ 15 public class CharRoomServer implements Runnable{ 16 17 private ServerSocketChannel serverSocketChannel = null; 18 19 private Selector selector = null; 20 21 public static final int PORT_NUM = 1198; 22 23 private boolean active = true; 24 25 private Charset charset = Charset.forName("UTF-8"); 26 27 private List<String> users = new ArrayList<String>(); 28 29 private ByteBuffer byteBuffer = ByteBuffer.allocate(2*1024); 30 31 public static final String protocol = "#user#"; 32 33 public CharRoomServer() { 34 this.init(); 35 } 36 37 public void init() { 38 try { 39 selector = Selector.open(); 40 serverSocketChannel = ServerSocketChannel.open(); 41 serverSocketChannel.socket().bind(new InetSocketAddress(PORT_NUM)); 42 serverSocketChannel.configureBlocking(false); 43 serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); 44 } catch (IOException e) { 45 e.printStackTrace(); 46 } 47 } 48 49 public void run() { 50 System.out.println("开始监听。。。。"); 51 while (active) { 52 try { 53 //非阻塞接受连接 54 // int s = selector.selectNow(); 55 56 //阻塞连接 57 int s = selector.select(); 58 59 System.out.println("服务端接受到连接总数"+selector.keys().size()); 60 } catch (IOException e) { 61 e.printStackTrace(); 62 } 63 System.out.println("服务端接受到的选择连接数"+selector.selectedKeys().size()); 64 Iterator<SelectionKey> keys = selector.selectedKeys().iterator(); 65 while (keys.hasNext()) { 66 SelectionKey k = keys.next(); 67 keys.remove(); 68 //处理逻辑 69 doHandler(selector, k); 70 } 71 } 72 } 73 74 private void doHandler(Selector selector, SelectionKey k) { 75 try { 76 //连接事件 77 if (k.isConnectable()) { 78 System.out.println("Connectable 连接事件"); 79 } else if (k.isAcceptable()) { 80 ServerSocketChannel ser = (ServerSocketChannel) k.channel(); 81 if (ser == serverSocketChannel) { 82 System.out.println("同一个连接"); 83 } 84 SocketChannel socketChannel = ser.accept(); 85 socketChannel.configureBlocking(false); 86 socketChannel.register(selector, SelectionKey.OP_READ); 87 socketChannel.write(charset.encode("please enter login name:")); 88 89 //设置k为接受事件,准备接受其它请求? 90 91 } else if (k.isReadable()) { 92 //获取客户端连接 93 SocketChannel socketChannel = (SocketChannel) k.channel(); 94 StringBuffer content = new StringBuffer(); 95 int sum = 0; 96 try { 97 byteBuffer.clear(); 98 while ((sum = socketChannel.read(byteBuffer)) > 0) { 99 byteBuffer.flip(); 100 content.append(charset.decode(byteBuffer)); 101 } 102 System.out.println(sum); 103 //判断客户端连接关闭 104 if (sum == -1) { 105 socketChannel.close(); 106 System.out.println("1--关闭连接"); 107 } 108 109 System.out.println("服务端:监听:"+ content.toString()); 110 } catch (Exception e) { 111 System.out.println("2--关闭连接"); 112 k.cancel(); 113 if (null != socketChannel) { 114 socketChannel.close(); 115 } 116 } 117 if (content.length() > 0) { 118 //按照协议切分内容 119 String[] contents = content.toString().split(protocol); 120 //登陆用户 121 if (contents != null && contents.length == 1) { 122 String user = contents[0]; 123 if (users.contains(user)) { 124 socketChannel.write(charset.encode("登陆用户已存在!")); 125 } else { 126 users.add(user); 127 //获取在线人数 128 int i = onlineCount(selector); 129 //广播登陆消息给当前房间所有人 130 brokerMessage(selector, k, "欢迎"+user+"登陆,当前第"+i+"号"); 131 } 132 } else if (contents != null && contents.length > 1) { 133 String message = contents[0] + "say :" + contents[1]; 134 brokerMessage(selector, k, message); 135 } 136 } 137 } else if (k.isWritable()) { 138 139 } 140 } catch (Exception e) { 141 e.printStackTrace(); 142 } 143 } 144 145 /** 146 * 广播消息 147 * @param content 148 */ 149 private void brokerMessage(Selector selector, SelectionKey k, String content) { 150 for (SelectionKey key : selector.keys()) { 151 if (key.channel() instanceof SocketChannel && key != k) { 152 try { 153 SocketChannel sc = (SocketChannel) key.channel(); 154 sc.write(charset.encode(content)); 155 } catch (IOException e1) { 156 e1.printStackTrace(); 157 } 158 } 159 } 160 } 161 162 /** 163 * 统计在线人数 164 * @param selector 165 * @return 166 */ 167 private int onlineCount(Selector selector) { 168 169 return 0; 170 } 171 172 public static void main(String[] args) { 173 System.out.println("开始启动服务"); 174 new Thread(new CharRoomServer()).start(); 175 System.out.println("服务启动"); 176 } 177 }