Java网络编程(9)NIO - 群聊系统
目标
完成一个群聊系统:
- 服务器可接收多个客户端的连接并接收信息
- 服务器向除了发送消息的客户端的其他客户端发送消息
- 客户端可以发送消息和接收消息
完成
服务器
package com.company.GroupChat;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;//群聊服务器
public class GroupChatServer {private final int Port = 9999;//使用到的属性private Selector selector;private ServerSocketChannel serverSocketChannel;private SocketChannel socketChannel;//构造器完成服务器连接操作public GroupChatServer() throws Exception {//打开selector和serverSocketChannelselector = Selector.open();serverSocketChannel = ServerSocketChannel.open();//设置非阻塞serverSocketChannel.configureBlocking(false);//监听端口serverSocketChannel.socket().bind(new InetSocketAddress(Port));//注册serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);}//读取消息的方法public static void main(String[] args) throws Exception {GroupChatServer server = new GroupChatServer();server.Listen();}//设置一个监听方法,监听事件public void Listen() throws Exception {while (true) {int cout=selector.select();//selector监控if (cout > 0) {//获得集合迭代器Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();while (keyIterator.hasNext()) {//得到该SelectionKeySelectionKey key = keyIterator.next();//判断事件if (key.isAcceptable()) {SocketChannel socketChannel = serverSocketChannel.accept();//设置非阻塞socketChannel.configureBlocking(false);//注册,监听读事件socketChannel.register(selector, SelectionKey.OP_READ);System.out.println("客户端:" + socketChannel.getRemoteAddress() + " 已上线");}if (key.isReadable()) {send(key);}//移除已经处理的SelectionKeykeyIterator.remove();}}//连接出现异常,应该是客户端下线}}//发送消息public void send(SelectionKey key) {//得到ChannelSocketChannel channel = null;//读取try {channel = (SocketChannel) key.channel();//创建bufferByteBuffer buffer = ByteBuffer.allocate(1024);int count = channel.read(buffer);//读取到了信息if (count > 0) {String msg = new String(buffer.array());System.out.println("客户端发送的消息:" + msg);//转发消息Forward(msg, channel);}} catch (IOException e) {try {System.out.println(channel.getRemoteAddress() + "已下线。。。");//取消注册key.cancel();//关闭通道channel.close();} catch (IOException e1) {e1.printStackTrace();}}}//转发消息的方法//需要知道消息和自身通道(转发除自身外的通道)public void Forward(String msg, SocketChannel self) throws IOException {System.out.println("消息转发中。。。");//得到所有注册在选择器上的通道for (SelectionKey key : selector.keys()) {//得到通道Channel channel = key.channel();//排除自己和非SocketChannelif (channel instanceof SocketChannel && channel != self) {SocketChannel sc = (SocketChannel) channel;//创建bufferByteBuffer buffer = ByteBuffer.wrap(msg.getBytes());//写入sc.write(buffer);}}}
}
客户端
package com.company.GroupChat;import javafx.scene.transform.Scale;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectableChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Scanner;public class GroupChatClient {//常用的属性private final String IP="127.0.0.1";private final int Port=9999;private Selector selector;private SocketChannel socketChannel;private String clientname;//构造方法public GroupChatClient() throws Exception{//打开selector = Selector.open();//连接socketChannel = SocketChannel.open(new InetSocketAddress(IP,Port));//设置非阻塞socketChannel.configureBlocking(false);//注册,监听read方法socketChannel.register(selector, SelectionKey.OP_READ);//得到客户端名字clientname=socketChannel.getLocalAddress().toString().substring(1);System.out.println(clientname+" 准备就绪。。。");}//接收信息public void Receive() throws IOException {int sel=selector.select();//接收到事件if (sel > 0){//迭代得到的SelectionKey集合Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();while (iterator.hasNext()){//获得SelectionKeySelectionKey key = iterator.next();if (key.isReadable()){//得到通道SocketChannel channel = (SocketChannel)key.channel();//buffer获得信息ByteBuffer buffer = ByteBuffer.allocate(1024);//从通道中读出channel.read(buffer);System.out.println(new String(buffer.array()));}iterator.remove();}}elseSystem.out.println("没有可用通道");}public void Send(String str) throws IOException {str=clientname+" : "+str;ByteBuffer buffer = ByteBuffer.wrap(str.getBytes());//写入socketChannel.write(buffer);}public static void main(String[] args) throws Exception {GroupChatClient chatClient=new GroupChatClient();new Thread(){public void run() {while (true){try {chatClient.Receive();Thread.currentThread().sleep(3000);} catch (IOException e) {e.printStackTrace();} catch (InterruptedException e) {e.printStackTrace();}}}}.start();//发送数据Scanner scanner=new Scanner(System.in);//一行一行的输入while (scanner.hasNext()){String msg=scanner.nextLine();chatClient.Send(msg);}}}
结果
完成的代码步骤都在注释里
实验结果:
客户端连接时打印上线消息
客户端发送消息:
服务器转发:
其他客户端接收消息:
Java网络编程(9)NIO - 群聊系统相关推荐
- (六)Netty网络编程应用实例-群聊系统
实例要求: 编写一个NIO群聊系统,实现服务器端和客户端之间的数据简单通讯(非阻塞) 实现多人群聊 服务器端:可以监测用户上线,离线,并实现消息转发功能 客户端:通过channel可以无阻塞发送消息给 ...
- NIO网络编程应用实例——群聊系统
GroupChatServer.java package com.atguigu.nio.groupchat;import java.io.IOException; import java.net.I ...
- Java NIO群聊系统
实例要求: 1.编写一个 NIO 群聊系统,实现服务器端和客户端之间的数据简单通讯(非阻塞) 2.实现多人群聊 3.服务器端:可以监测用户上线,离线,并实现消息转发功能 4.客户端:通过 Channe ...
- Java网络编程与NIO学习总结
#Java网络编程与NIO学习总结 这篇总结主要是基于我之前Java网络编程与NIO系列文章而形成的的.主要是把重要的知识点用自己的话说了一遍,可能会有一些错误,还望见谅和指点.谢谢 #更多详细内容可 ...
- Java网络编程和NIO详解开篇:Java网络编程基础
老曹眼中的网络编程基础 转自:https://mp.weixin.qq.com/s/XXMz5uAFSsPdg38bth2jAA 我们是幸运的,因为我们拥有网络.网络是一个神奇的东西,它改变了你和我的 ...
- 手写一个NIO群聊系统
一.浅谈NIO 1. 什么是NIO? Java NIO:同步非阻塞,服务器实现模式为一个线程处理多个请求(连接),即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有 I/ ...
- java 网络编程和NIO
1.软件结构 C/S结构 :全称为Client/Server结构,是指客户端和服务器结构.常见程序有QQ.迅雷等软件. 特点: 客户端和服务器是分开的,需要下载客户端,对网络要求相对低, 服务器压力小 ...
- Java网络编程与NIO详解14:Tomcat 常见面试题汇总
1.Tomcat的缺省端口是多少,怎么修改? 1)找到Tomcat目录下的conf文件夹 2)进入conf文件夹里面找到server.xml文件 3)打开server.xml文件 4)在server. ...
- Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制
JAVA 中原生的 socket 通信机制 转载自:https://github.com/jasonGeng88/blog 当前环境 jdk == 1.8 知识点 socket 的连接处理 IO 输入 ...
- java网络编程3 -- NIO一些简单说明
2019独角兽企业重金招聘Python工程师标准>>> 什么是NIO NIO是相对有BIO而言的,就是非阻塞性IO . 什么叫非阻塞性 ?我举一个简单的例子: 比如,你客户端发送了一 ...
最新文章
- Python基础之函数2 (参数的返回值)
- Nginx动态、静态分离,Nginx配置中做适配
- 关于类DOTA游戏多样化技能系统的设计思考
- php 代码如何使用,PHP如何使用strval()函数?用法和代码示例
- JUnit4参数化和理论示例
- php mvc 高性能框架,swoolefy-基于swoole扩展实现的高性能的微服务和mvc框架
- 互联网晚报 | 9月5日 星期日 | 美菜回应大规模裁员;网易云音乐Q2毛利率首次转正;美团展示数字人民币新应用...
- 罗永浩“真还传”再出番外篇,被执行1800万,交个朋友回应来了…
- redis永久化存储
- 使用IPV6 ACL对telnet登陆进行限定
- 独立的定义有多重等价表述方式
- 矩阵论第一章总结(思维导图)
- 正则表达式最后的/i是不区分大小写的意思
- 药店计算机无法运行整改报告,药店整改报告模板网络版(电子版)
- Axure 9 实战案例,动态面板的应用 3,京东的拖动拼图登录验证
- 2017.10.14晚,用迅雷下载大部分BT资源出现失败,tracker服务器被封了?FK
- 裁剪用C语言,多边形裁剪
- 解决QT-mingw32编译“ too many sections(...)”问题
- 最新友价T5仿虚拟交易商城网站源码+PHP内核
- 几种Java常用序列化框架的选型与对比