NIO -- 群聊系统

基本要求

  1. 群聊系统实现服务器端和客户端之间的数据简单通讯(非阻塞)。
  2. 实现多人群聊
  3. 服务器端:可以监测用户上线、下线、、并实现消息转发。
  4. 客户端:可无阻塞发送消息给其他所有用户,同时可以接受其他用户消息(由服务器转发得到)。

实现思路

  1. 先编写服务器,服务器启动监听、
  2. 服务器可接受客户端信息进行转发
  3. 再编写客户端,连接服务器、发送消息、接受消息

具体代码

服务器端

public class GroupChatServer {//定义属性private Selector selector;private ServerSocketChannel listenChannel;private static final int PORT = 54188;//定义相关的属性private final String HOST = "192.168.41.1"; // 服务器的ip//构造器//初始化工作public GroupChatServer() {try {//得到选择器selector = Selector.open();//ServerSocketChannellistenChannel =  ServerSocketChannel.open();//绑定端口listenChannel.socket().bind(new InetSocketAddress(HOST, PORT));//设置非阻塞模式listenChannel.configureBlocking(false);//将该listenChannel 注册到selectorlistenChannel.register(selector, SelectionKey.OP_ACCEPT);}catch (IOException e) {e.printStackTrace();}}//监听public void listen() {System.out.println("监听线程: " + Thread.currentThread().getName());try {//循环处理while (true) {int count = selector.select();if(count > 0) {//有事件处理//遍历得到selectionKey 集合Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();while (iterator.hasNext()) {//取出selectionkeySelectionKey key = iterator.next();//监听到acceptif(key.isAcceptable()) {SocketChannel sc = listenChannel.accept();sc.configureBlocking(false);//将该 sc 注册到seletorsc.register(selector, SelectionKey.OP_READ);//提示System.out.println(sc.getRemoteAddress() + " 上线 ");}if(key.isReadable()) { //通道发送read事件,即通道是可读的状态//处理读 (专门写方法..)readData(key);}//当前的key 删除,防止重复处理iterator.remove();}} else {System.out.println("等待....");}}}catch (Exception e) {e.printStackTrace();}finally {//发生异常处理....}}//读取客户端消息private void readData(SelectionKey key) {//取到关联的channleSocketChannel channel = null;try {//得到channelchannel = (SocketChannel) key.channel();//创建bufferByteBuffer buffer = ByteBuffer.allocate(1024);int count = channel.read(buffer);//根据count的值做处理if(count > 0) {//把缓存区的数据转成字符串String msg = new String(buffer.array());//输出该消息System.out.println("form 客户端: " + msg);//向其它的客户端转发消息(去掉自己), 专门写一个方法来处理sendInfoToOtherClients(msg, channel);}}catch (IOException e) {try {System.out.println(channel.getRemoteAddress() + " 离线了..");//取消注册key.cancel();//关闭通道channel.close();}catch (IOException e2) {e2.printStackTrace();;}}}//转发消息给其它客户(通道)private void sendInfoToOtherClients(String msg, SocketChannel self ) throws  IOException{System.out.println("服务器转发消息中...");System.out.println("服务器转发数据给客户端线程: " + Thread.currentThread().getName());//遍历 所有注册到selector 上的 SocketChannel,并排除 selffor(SelectionKey key: selector.keys()) {//通过 key  取出对应的 SocketChannelChannel targetChannel = key.channel();//排除自己if(targetChannel instanceof  SocketChannel && targetChannel != self) {//转型SocketChannel dest = (SocketChannel)targetChannel;//将msg 存储到bufferByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());//将buffer 的数据写入 通道dest.write(buffer);}}}public static void main(String[] args) {//创建服务器对象GroupChatServer groupChatServer = new GroupChatServer();groupChatServer.listen();}
}

客户端

public class GroupChatClient {//定义相关的属性private final String HOST = "192.168.41.1"; // 服务器的ipprivate final int PORT = 54188; //服务器端口private Selector selector;private SocketChannel socketChannel;private String username;//构造器, 完成初始化工作public GroupChatClient() throws IOException {selector = Selector.open();//连接服务器socketChannel = SocketChannel.open(new InetSocketAddress(HOST, PORT));//设置非阻塞socketChannel.configureBlocking(false);//将channel 注册到selectorsocketChannel.register(selector, SelectionKey.OP_READ);//得到usernameusername = socketChannel.getLocalAddress().toString().substring(1);System.out.println(username + " is ok...");}//向服务器发送消息public void sendInfo(String info) {info = username + " 说:" + info;try {socketChannel.write(ByteBuffer.wrap(info.getBytes()));}catch (IOException e) {e.printStackTrace();}}//读取从服务器端回复的消息public void readInfo() {try {int readChannels = selector.select();if(readChannels > 0) {//有可以用的通道Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();while (iterator.hasNext()) {SelectionKey key = iterator.next();if(key.isReadable()) {//得到相关的通道SocketChannel sc = (SocketChannel) key.channel();//得到一个BufferByteBuffer buffer = ByteBuffer.allocate(1024);//读取sc.read(buffer);//把读到的缓冲区的数据转成字符串String msg = new String(buffer.array());System.out.println(msg.trim());}}iterator.remove(); //删除当前的selectionKey, 防止重复操作} else {//System.out.println("没有可以用的通道...");}}catch (Exception e) {e.printStackTrace();}}@SuppressWarnings("resource")public static void main(String[] args) throws Exception {//启动我们客户端final GroupChatClient chatClient = new GroupChatClient();//启动一个线程, 每个3秒,读取从服务器发送数据new Thread() {public void run() {while (true) {chatClient.readInfo();try {Thread.sleep(3000);}catch (InterruptedException e) {e.printStackTrace();}}}}.start();//发送数据给服务器端Scanner scanner = new Scanner(System.in);while (scanner.hasNextLine()) {String s = scanner.nextLine();chatClient.sendInfo(s);}}}

结果呈现

NIO 网络编程之群聊系统相关推荐

  1. Java NIO网络编程之群聊系统

    概述 对ServerSocketChannel.SocketChannel.SelectionKey有一定的理解和了解对应API. NIO非阻塞网络编程相关关系梳理: 以下概念: ServerSock ...

  2. Netty工作笔记0029---NIO 网络编程应用--群聊系统4--客户端编写2

    技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152 然后组织客户端去 客户端中去新建一个线程去调用客户端的,readInfo去读取数据就可以了. 然后 ...

  3. Netty工作笔记0028---NIO 网络编程应用--群聊系统3--客户端编写1

    技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152 这个是客户端要做的事情. 然后这里构造方法,连接服务器 这里构造器完成初始化,主要是 连接服务器, ...

  4. Netty工作笔记0027---NIO 网络编程应用--群聊系统2--服务器编写2

    技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152 注意发送消息的时候,要排除发消息的他自己. 开始写给其他客户端发送消息. 这里读取对应的发过来的通 ...

  5. Netty工作笔记0026---NIO 网络编程应用--群聊系统1---编写服务器1

    技术交流QQ群[JAVA,C++,Python,.NET,BigData,AI]:170933152

  6. (六)Netty网络编程应用实例-群聊系统

    实例要求: 编写一个NIO群聊系统,实现服务器端和客户端之间的数据简单通讯(非阻塞) 实现多人群聊 服务器端:可以监测用户上线,离线,并实现消息转发功能 客户端:通过channel可以无阻塞发送消息给 ...

  7. Java NIO群聊系统

    实例要求: 1.编写一个 NIO 群聊系统,实现服务器端和客户端之间的数据简单通讯(非阻塞) 2.实现多人群聊 3.服务器端:可以监测用户上线,离线,并实现消息转发功能 4.客户端:通过 Channe ...

  8. Netty学习笔记:二、NIO网络应用实例-群聊系统

    实例要求: 编写一个NIO群聊系统,实现服务器端和多个客户端之间的数据简单通讯(非阻塞): 实现多人群聊: 服务器端:可以监测用户上线.离线,并实现消息转发功能: 客户端:通过channel可以无阻塞 ...

  9. 手写一个NIO群聊系统

    一.浅谈NIO 1. 什么是NIO? ​​Java NIO​​:同步非阻塞,服务器实现模式为一个线程处理多个请求(连接),即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有 ​​I/ ...

  10. 4.基于NIO的群聊系统

    [README] 1.本文总结自B站<netty-尚硅谷>,很不错: 2.文末有错误及解决方法: [1]群聊需求 1)编写一个 NIO 群聊系统,实现服务器端和客户端之间的数据简单通讯(非 ...

最新文章

  1. 一个困扰数学家30多年的分类问题,终于被解决了!
  2. 微软终于想通把Script56文档更新了
  3. Android有返回值的Activity
  4. Python Django 可变参数代码示例
  5. boost::hana::range_c用法的测试程序
  6. sql 触发器_一键生成某个sql的html--记录执行计划、统计信息、触发器等
  7. 美团配送系统架构演进实践
  8. 到底谁在使用低代码?钉钉低代码用户画像:非IT人员占8成
  9. jQuery插件:Tiny Scrollbar滚动条插件(滚动条美化、默认滚动条)
  10. 第二十九章:学校招生
  11. 《软件工程》课程改进意见
  12. Solr查询参数sort(排序)
  13. python金山词霸单词本批量导入
  14. 在Debian Linux下用MAME模拟器玩街机游戏
  15. 计算非等间隔离散曲线的曲率
  16. 2020年起重机司机(限桥式起重机)考试及起重机司机(限桥式起重机)答案解析
  17. Matlab笔记——License Manager Error -9解决办法——matlab反激活
  18. 手机端页面rem自适应脚本
  19. 集精准翻译与学习助手于一身 搜狗翻译APP实现重磅升级
  20. Java错题集(十四)

热门文章

  1. 蓝桥杯 杨辉三角形 python组省赛真题
  2. vscode中文乱码
  3. 【学术】推荐给从事科研的青年人——石墨烯教父:从千年博后到物理诺奖的心路历程
  4. RDKit | RDKit中处理分子Mol对象
  5. 【基于JavaEE的医院药品管理系统的设计与实现】
  6. log4j2配置文件详解
  7. 乐高ev3python教程_入门篇丨使用EV3机器人,趣味学习Python编程语言~
  8. 使用jrtplib库收发视频流
  9. OFFICE InfoPath 教程
  10. Jensen不等式及其扩展