这几天在学习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 }
View Code

相关文章: