Java NIO示例:多人网络聊天室完整代码
生活随笔
收集整理的這篇文章主要介紹了
Java NIO示例:多人网络聊天室完整代码
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
服務端:?
package cn.zhangxueliang.herostory.chatroom;import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.*; import java.nio.charset.Charset; import java.util.HashSet; import java.util.Iterator; import java.util.Set;/*** @ProjectName herostory3* @ClassName ChatRoomServer* @Desicription TODO* @Author Zhang Xueliang* @Date 2019/12/11 13:58* @Version 1.0** * 網絡多客戶端聊天室* * 功能1: 客戶端通過Java NIO連接到服務端,支持多客戶端的連接* * 功能2:客戶端初次連接時,服務端提示輸入昵稱,如果昵稱已經有人使用,提示重新輸入,如果昵稱唯一,則登錄成功,之后發送消息都需要按照規定格式帶著昵稱發送消息* * 功能3:客戶端登錄后,發送已經設置好的歡迎信息和在線人數給客戶端,并且通知其他客戶端該客戶端上線* * 功能4:服務器收到已登錄客戶端輸入內容,轉發至其他登錄客戶端。* ** * TODO 客戶端下線檢測***/ public class ChatRoomServer {private Selector selector=null;static final int port=9999;private Charset charset=Charset.forName("UTF-8");private static HashSet<String> users = new HashSet<>();private static String USER_EXIST="system message : user exist, please change a name用戶名已存在,請更換一個名稱";private static String USER_CONTENT_SPLIT="#@#";private static boolean flag=false;public void init() throws Exception{selector=Selector.open();ServerSocketChannel server = ServerSocketChannel.open();server.bind(new InetSocketAddress(port));server.configureBlocking(false);server.register(selector, SelectionKey.OP_ACCEPT);System.out.println("Server is listening now...服務端正在監聽中");while (true){int readyChannels = selector.select();if (readyChannels==0){continue;}Set<SelectionKey> selectionKeys = selector.selectedKeys(); //可以通過這個方法,知道可用通道的集合Iterator<SelectionKey> keyIterator = selectionKeys.iterator();while (keyIterator.hasNext()){SelectionKey sk = keyIterator.next();keyIterator.remove();dealWithSelectionKey(server,sk);}}}private void dealWithSelectionKey(ServerSocketChannel server, SelectionKey sk) throws IOException {if (sk.isAcceptable()){SocketChannel sc = server.accept();sc.configureBlocking(false);sc.register(selector,SelectionKey.OP_READ);sk.interestOps(SelectionKey.OP_ACCEPT);System.out.println("Server is listening fron client: "+sc.getRemoteAddress());sc.write(charset.encode("please input your name."));}if (sk.isReadable()){SocketChannel sc = (SocketChannel) sk.channel();ByteBuffer buff = ByteBuffer.allocate(1024);StringBuilder content = new StringBuilder();try{while (sc.read(buff)>0){buff.flip();content.append(charset.decode(buff));}System.out.println("Server is listening from client: "+sc.getRemoteAddress()+" data rev is: "+content);sk.interestOps(SelectionKey.OP_READ);}catch (IOException io){sk.cancel();if (sk.channel()!=null){sk.channel().close();}}if (content.length()>0){String[] arrayContent = content.toString().split(USER_CONTENT_SPLIT);if (arrayContent!=null && arrayContent.length==1){String name = arrayContent[0];if (users.contains(name)){sc.write(charset.encode(USER_EXIST));}else {users.add(name);int num = OnlineNum(selector);String message = "welcome "+name+" to char room! Online numbers is :"+num;BroadCast(selector,null,message);}}else if (arrayContent!=null && arrayContent.length>1){String name = arrayContent[0];String message = content.substring(name.length()+USER_CONTENT_SPLIT.length());message=name+" say "+message;if (users.contains(name)){BroadCast(selector,sc,message);}}}}}private void BroadCast(Selector selector, SocketChannel except, String content) throws IOException {for (SelectionKey key:selector.keys()){Channel targetchannel = key.channel();if (targetchannel instanceof SocketChannel && targetchannel!=except){SocketChannel dest = (SocketChannel) targetchannel;dest.write(charset.encode(content));}}}private int OnlineNum(Selector selector) {int res=0;for (SelectionKey key:selector.keys()){SelectableChannel targetChannel = key.channel();if (targetChannel instanceof SocketChannel){res++;}}return res;}public static void main(String[] args) throws Exception {new ChatRoomServer().init();}}客戶端:
package cn.zhangxueliang.herostory.chatroom;import java.io.IOException; import java.net.InetSocketAddress; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.nio.charset.Charset; import java.util.Iterator; import java.util.Scanner; import java.util.Set; import java.nio.ByteBuffer; /*** @ProjectName herostory3* @ClassName ChatRoomClient* @Desicription TODO* @Author Zhang Xueliang* @Date 2019/12/11 14:33* @Version 1.0**/ public class ChatRoomClient {private Selector selector = null;static final int port = 9999;private Charset charset = Charset.forName("UTF-8");private SocketChannel sc = null;private String name = "";private static String USER_EXIST = "system message: user exist, please change a name";private static String USER_CONTENT_SPILIT = "#@#";public void init() throws IOException{selector = Selector.open();//連接遠程主機的IP和端口sc = SocketChannel.open(new InetSocketAddress("127.0.0.1",port));sc.configureBlocking(false);sc.register(selector, SelectionKey.OP_READ);//開辟一個新線程來讀取從服務器端的數據new Thread(new ClientThread()).start();//在主線程中 從鍵盤讀取數據輸入到服務器端Scanner scan = new Scanner(System.in);while(scan.hasNextLine()){String line = scan.nextLine();if("".equals(line)) continue; //不允許發空消息if("".equals(name)) {name = line;line = name+USER_CONTENT_SPILIT;} else {line = name+USER_CONTENT_SPILIT+line;}sc.write(charset.encode(line));//sc既能寫也能讀,這邊是寫}}private class ClientThread implements Runnable{public void run(){try{while(true) {int readyChannels = selector.select();if(readyChannels == 0) continue;Set selectedKeys = selector.selectedKeys(); //可以通過這個方法,知道可用通道的集合Iterator keyIterator = selectedKeys.iterator();while(keyIterator.hasNext()) {SelectionKey sk = (SelectionKey) keyIterator.next();keyIterator.remove();dealWithSelectionKey(sk);}}}catch (IOException io){}}private void dealWithSelectionKey(SelectionKey sk) throws IOException {if(sk.isReadable()){//使用 NIO 讀取 Channel中的數據,這個和全局變量sc是一樣的,因為只注冊了一個SocketChannel//sc既能寫也能讀,這邊是讀SocketChannel sc = (SocketChannel)sk.channel();ByteBuffer buff = ByteBuffer.allocate(1024);String content = "";while(sc.read(buff) > 0){buff.flip();content += charset.decode(buff);}//若系統發送通知名字已經存在,則需要換個昵稱if(USER_EXIST.equals(content)) {name = "";}System.out.println(content);sk.interestOps(SelectionKey.OP_READ);}}}public static void main(String[] args) throws IOException{new ChatRoomClient().init();} } 與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Java NIO示例:多人网络聊天室完整代码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 将protobuf文档转换成java代码
- 下一篇: Java实现字符串反转的四种方式代码示例