Hello, I’m Tong Ge, and this is the fourth installment of the Netty series.

Welcome to my official number Tong Elder brother read source code systematically learn source code & architecture knowledge.

Introduction to the

In the last chapter, we learned the BIO/NIO/AIO story in Java. In this chapter, we will use pure NIO to implement a “group chat system” that becomes more and more addictive.

Business logic analysis

First, let’s analyze the function points of group chat:

(1) Join a group chat and inform others;

(2) speak up and inform others;

(3) Quit the group chat and inform others;

These three functions are enough for a simple group chat system. In order to record user information, a user ID is automatically assigned to the user when he joins a group chat.

Business implementation

The code:

Private static class ChatHolder {// We are using only one thread, Static final Map<SocketChannel, String> USER_MAP = new ConcurrentHashMap<>(); @param socketChannel */ static void join(socketChannel socketChannel) { This article from male from, "tong elder brother read source" String userId = "user" + ThreadLocalRandom. Current () nextInt (Integer. MAX_VALUE); Send (socketChannel, "your id is" + userId + "\n\r"); For (SocketChannel channel: user_map.keyset ()) {send(channel, userId + "join group chat" + "\n\r"); } // Add the current user to the map user_map. put(socketChannel, userId); } /** * exit group chat * @param socketChannel */ static void quit(socketChannel socketChannel) {String userId = USER_MAP.get(socketChannel); Send (socketChannel, "you quit the group chat" + "\n\r"); USER_MAP.remove(socketChannel); for (SocketChannel channel : USER_MAP.keySet()) { if (channel ! = socketChannel) {send(channel, userId + "quit group chat" + "\n\r"); Public static void propagate(socketChannel propagate, socketChannel propagate)  String content) { String userId = USER_MAP.get(socketChannel); for (SocketChannel channel : USER_MAP.keySet()) { if (channel ! = socketChannel) { send(channel, userId + ": " + content + "\n\r"); @param socketChannel @param MSG/static void send(socketChannel socketChannel, String msg) { try { ByteBuffer writeBuffer = ByteBuffer.allocate(1024); writeBuffer.put(msg.getBytes()); writeBuffer.flip(); socketChannel.write(writeBuffer); } catch (Exception e) { e.printStackTrace(); }}}Copy the code

Server code

The server code uses the NIO implementation in the previous chapter directly, except that the business logic implemented above is inserted into the appropriate events in time.

(1) Accept event, that is, when the connection is established, it means joining the group chat;

(2) The read event, when reading data, indicates that someone has spoken;

(3) When the connection is disconnected, it means that you have quit the group chat;

OK, go directly to the code. In order to distinguish it from the code in the previous chapter, Tong Brother has specially added some marks:

public class ChatServer { public static void main(String[] args) throws IOException { Selector selector = Selector.open(); ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.bind(new InetSocketAddress(8080)); serverSocketChannel.configureBlocking(false); / / will accept events to bind to the selector on the serverSocketChannel. Register (selector, SelectionKey. OP_ACCEPT); While (true) {// block selector on select. Select (); Set<SelectionKey> selectionKeys = selector.selectedKeys(); SelectKeys Iterator<SelectionKey> Iterator = selectionkeys.iterator (); while (iterator.hasNext()) { SelectionKey selectionKey = iterator.next(); / / if the accept event if (selectionKey isAcceptable ()) = {ServerSocketChannel SSC (ServerSocketChannel) selectionKey.channel(); SocketChannel socketChannel = ssc.accept(); System.out.println("accept new conn: " + socketChannel.getRemoteAddress()); socketChannel.configureBlocking(false); socketChannel.register(selector, SelectionKey.OP_READ); Chatholder. join(socketChannel); // Join a group chat. } else if (selectionKey.isreadable ()) {SocketChannel SocketChannel = (SocketChannel) selectionkey.channel ();  ByteBuffer buffer = ByteBuffer.allocate(1024); Int length = socketchannel.read (buffer); int length = socketchannel.read (buffer); if (length > 0) { buffer.flip(); byte[] bytes = new byte[buffer.remaining()]; // Read the data into the byte array buffer.get(bytes); String Content = new String(bytes, "UTF-8").replace("\r\n", ""); If (content.equalsignorecase ("quit")) {// Exit the group chat. selectionKey.cancel(); socketChannel.close(); } else {// propagate, propagate(socketChannel, content); } } } iterator.remove(); }}}}Copy the code

test

Open four XSHELL clients, connect to Telnet 127.0.0.1 8080, and you’re ready to start a group chat.

Tong elder brother discovers, oneself chat with oneself also can be addicted, completely can’t stop, not line, I go again from chat for a while ^^

conclusion

In this paper, Tong Elder brother followed everyone to achieve the “group chat system”, remove the comments only about 100 lines of code, isn’t it very simple? That’s the beauty of NIO network programming, and I find writing network programming addictive too

The problem

We didn’t use NIO to implement the client in either chapter. Do you know how?

A ServerSocketChannel is used to connect to the server. A SocketChannel is equivalent to a Connection.

Finally, welcome to my official number Tong elder brother read the source code systematically learn the knowledge of source code & architecture.