java中nio怎么实现聊天,JAVA-NIO实现聊天室详细代码说明

JAVA-NIO实现聊天室详细代码说明

JAVA-NIO实现聊天室详细代码说明

github源码:https://github.com/JolyouLu/JAVAIO.git

src\main\java\com\JolyouLu\nio\groupchat 文件夹下

public class GroupChatServer {

//定义属性

private Selector selector;

private ServerSocketChannel listenChannel;

private static final int PORT = 6666;

//构造器 完成初始化工作

public GroupChatServer() {

try {

//得到选择器

selector = Selector.open();

//初始化ServerSocketChannel

listenChannel = ServerSocketChannel.open();

//绑定端口

listenChannel.socket().bind(new InetSocketAddress(PORT));

//设置非阻塞模式

listenChannel.configureBlocking(false);

//将来listenChannel注册到Selector

listenChannel.register(selector, SelectionKey.OP_ACCEPT);

}catch (IOException e){

e.printStackTrace();

}

}

//监听

public void listen(){

try {

//循环监听

while (true){

int count = selector.select(2000); //阻塞2秒监听,通道有没有事件发生

if (count > 0){ //返回>0 有事件要处理

//遍历selectedKeys集合

Iterator iterator = selector.selectedKeys().iterator();

while (iterator.hasNext()){

//获取SelectionKey

SelectionKey key = iterator.next();

if (key.isAcceptable()){ //如果通道发生,客户端连接事件

//为连接的客户端,生成socketChannel

SocketChannel socketChannel = listenChannel.accept();

//切换非阻塞模式

socketChannel.configureBlocking(false);

//把socketChannel注册到selector中,并监听读事件

socketChannel.register(selector,SelectionKey.OP_READ);

//提示客户端连接上了

System.out.println(socketChannel.getRemoteAddress() + " 客户端 上线");

}

if (key.isReadable()){//如果通道发生,可读事件

//处理读

readData(key);

}

//清理读取的selectedKeys容器 防止重复处理

iterator.remove();

}

}

}

}catch (Exception e){

e.printStackTrace();

}finally {

}

}

//读取客户端消息

private void readData(SelectionKey key){

//定义一个SocketChannel

SocketChannel channel = null;

try {

//取到关联的channel

channel = (SocketChannel) key.channel();

//创建buffer

ByteBuffer buffer = ByteBuffer.allocate(1024);

int count = channel.read(buffer);

//根据count的值做处理

if (count > 0){ //读取到数据

//把缓冲区的数据转字符串

String msg = new String(buffer.array(), "GBK");

//输出消息

System.out.println("from 客户端:"+ msg);

//向其它客户端转发消息

sendInfoToOtherClients(msg,channel);

}

}catch (IOException e){

try {

System.out.println(channel.getRemoteAddress() + " 离线了..");

//取消注册

key.cancel();

//关闭通道

channel.close();

} catch (IOException ioException) {

ioException.printStackTrace();

}

}

}

//转发消息给其它客户端(channel)

private void sendInfoToOtherClients(String msg,SocketChannel self) throws IOException {

System.out.println("服务器转发消息中...");

//遍历 所有的注册到Selector的SocketChannel排查self

for (SelectionKey key : selector.keys()) {

//取出通道

Channel targetChannel = key.channel();

//targetChanneld的类型是SocketChannel,并且targetChannel不是自己

if (targetChannel instanceof SocketChannel && targetChannel != self){

//转型

SocketChannel dest = (SocketChannel)targetChannel;

//将来msg 存到buffer

ByteBuffer buffer = ByteBuffer.wrap(msg.getBytes("GBK"));

//将来buffer的数据写入通道

dest.write(buffer);

}

}

}

public static void main(String[] args) {

//初始化服务器对象

GroupChatServer chatServer = new GroupChatServer();

chatServer.listen();

}

}

客户端

public class GroupChatClient {

//定义相关属性

private final String HOST = "127.0.0.1"; //服务器IP

private final int PORT = 6666; //服务器端口

private Selector selector;

private SocketChannel socketChannel;

private String username;

//构造器,初始化

public GroupChatClient() {

try {

//得到选择器

selector = Selector.open();

//连接服务

socketChannel = SocketChannel.open(new InetSocketAddress(HOST,PORT));

//设置非阻塞

socketChannel.configureBlocking(false);

//将来socketChannel注册到Selector,关注读事件

socketChannel.register(selector, SelectionKey.OP_READ);

//得到username

username = socketChannel.getLocalAddress().toString().substring(1);

System.out.println(username + " is ok ...");

}catch (Exception e){

e.printStackTrace();

}

}

//向服务器发送消息

public void sendInfo(String info){

info = username + " 说:" + info;

try {

socketChannel.write(ByteBuffer.wrap(info.getBytes("GBK")));

}catch (IOException e){

e.printStackTrace();

}

}

//读取从服务器端回复的消息

public void readInfo(){

try {

int readChannels = selector.select(2000);

if (readChannels > 0){//有可用的通道

Iterator iterator = selector.selectedKeys().iterator();

while (iterator.hasNext()){

SelectionKey key = iterator.next();

if (key.isReadable()){

//得到相关的通道

SocketChannel socketChannel = (SocketChannel) key.channel();

//得到一个Buffer

ByteBuffer buffer = ByteBuffer.allocate(1024);

//buffer 读取通道数据

socketChannel.read(buffer);

//把读到缓冲区的数据转成字符串

String msg = new String(buffer.array());

System.out.println(msg.trim());

}

iterator.remove();

}

}

}catch (IOException e){

e.printStackTrace();

}

}

public static void main(String[] args) {

//启动客户端

GroupChatClient chatClient = new GroupChatClient();

//启动一个线程,每隔开3秒读取服务器发送的数据

new Thread(new Runnable() {

@Override

public void run() {

while (true){

chatClient.readInfo();

try {

Thread.currentThread().sleep(3000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}).start();

//发送数据

Scanner scanner = new Scanner(System.in);

while (scanner.hasNextLine()){

String s = scanner.nextLine();

chatClient.sendInfo(s);

}

}

}

测试

设置启动参数,当前类可以同时运行多个

05af2d7303337818dbb34eb38cd0e9b5.png

b6decadda5ecef207db3ea7f980ad314.png

0b930c45c4929fbb85178188be0a1fd4.png

8d7bda5fb2adee12101e0c19ea59aae8.png

JAVA-NIO实现聊天室详细代码说明相关教程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/245880.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vscode 调试_如何使用VSCode调试JS?

更多精彩,请点击上方蓝字关注我们!序言做前端开发的朋友经常需要使用Visual Studio Code编辑代码,很多朋友就想在VSCode调试JS代码,下面我们就介绍下如何配置操作。一、环境准备首先安装好VSCode,准备好一个JS项目&…

基于matlab的信号合成与分解,基于matlab的信号合成与分解

基于matlab的信号合成与分解 - I - 摘 要 为了便于进行周期信号的分析与处理,常要把复杂的周期信号进行分解,即将周期 信号分解为正余弦等此类基本信号的线性组合,通过对这些基本信号单元在时域和频域 特性的分析来达到了解信号特性的目的。本…

基站位置查询系统_木牛导航网络基站服务免费了!——更便捷、更高效、更省心!...

布谷飞飞劝早耕,春锄扑扑趁初晴。千层石树通行路,一带水田放水声。《山行》-- 姚鼐(Photo by Quang Nguyen Vinh)农业生产作为人类最传统的产业自古以来都讲究及时耕种,即抢农时根据气候适宜而进行季节性生产随着科技的发展,农业生…

php cgi进程很多win2008,php cgi.exe 太多 在 windowserver2008 apache 这个怎么样限制下?...

php cgi.exe 太多 在 windowserver2008 apache 这个怎么样限制下?mip版 关注:61 答案:2 悬赏:70解决时间 2021-02-24 01:48已解决2021-02-23 09:13php cgi.exe 太多 在 windowserver2008 apache 这个怎么样限制下?最佳答案2021-02-23 09:57可以设置最…

wince怎么刷carplay_Carplay支持仪表/HUD显示 宝马为全球超750000辆车发布OTA升级

【太平洋汽车网 新车频道】日前,宝马官方宣布,将从10月19日起为全球超过750000辆汽车提供iDrive 7.0最新版本的最重要的一次OTA升级。据悉,这项升级将有多项新功能加入,并重点支持Apple Carplay将导航等信息显示在HUD抬头显示和全…

php 如何调用redis,php如何调用redis

一、windows下php连接redis1、下载phpredishttps://github.com/nicolasff/phpredis/downloads2、根据你php版本,选择安装vc库,可以通过phpinfo();查看3、安装php_redis.dll模块将下载下来的php_redis模块放到php安装目录下的/ext/中,并在php.…

分析以太网帧结构_传统以太网中的——中继器及集线器

1.1 Repeater 中继器中继器工作在以太网的第一层即物理层, 两端口设备,主要功能是放大信号,从而延长信号在同一网络上传输的长度。中继器的存在主要是解决解决电信号长距离传播过程中的衰减问题,以增加信号强度和传播距离。Figure…

html表ge模板_精选甘特图模板,丰富又好用

你听说过甘特图吗?你可能不知道,也有可能是只是听说过但是并不了解。今天我们就来说一说甘特图吧!甘特图其实就是是通过标示出活动顺序和时间间隔来表示某一特定项目的顺序与时间之间的关系的一种图表。与时间表或日程规划表不同的部分是甘特…

oracle中调试存储过程,详解Oracle调试存储过程

详解Oracle调试存储过程一 调试关键步骤1、在要调试的存储过程右键,选择编辑以进行调试,截图如下:2、点击小瓢虫,弹出调试窗口,截图如下:3、输入7839员工编号,点击确认,进行调试&…

imp oracle full,Oracle 10g imp 之 full database (转官档)

Using Export and Import to Move a DatabaseBetweenPlatforms10g官档:The Export and Import utilities are the only method that Oracle supports for moving an existing Oracle database from one hardware platform. to another. This includes moving between UNIX and …

linux的apache安装在哪个目录,在linux系统下apache的默认安装路径在哪

如果采用RPM包安装,安装路径应在 /etc/httpd目录下。(学习教程推荐:apache)apache配置文件:/etc/httpd/conf/httpd.conf 可以修改相关的访问路径及配置Apache模块路径:/usr/sbin/apachectl 启动模块web目录:/var/www/h…

车子Linux系统,Linux车载系统Automotive Grade Linux

【中关村在线软件资讯】7月8日消息:Linux在车载系统上,并不想落后于苹果、谷歌等竞争对手,这不,Linux最近也推出了可定制的车载系统平台——Automotive Grade Linux,旨在建立一个未来智能汽车系统的标准。Linux车载系统…

linux ios开发环境,iOS开发环境搭建(Linux版)

iOS开发环境搭建(Linux版)2015-05-11 13:26:503057浏览必须申明的是,我们强烈建议大家在Mac下学习iOS应用开发,迫不得已才选择Windows和Linux。看到Linux的环境搭建步骤,早已凌乱。1. Ubuntu 10.10 iPhone Toolchain 4If you use Ubuntu 11.0…

pb9数据窗口中显示行数据与当前行区别_Hive的窗口函数

聚合函数(如sum()、avg()、max()等等)是针对定义的行集(组)执行聚集,每组只返回一个值。窗口函数也是针对定义的行集(组)执行聚集,可为每组返回多个值。如既要显示聚集前的数据,又要…

linux下shell脚本论文,Linux下Shell脚本编程

1、 shell脚本是什么它是一种脚本语言,并非编程语言。可以使用一些逻辑判断、循环等语法。可以自定义子函数,是系统命令的集合。shell脚本可以实现自动化运维,大大增加我们的工作效率。2、shell脚本结构以及执行方法开头行指定bash路径: #! /…

重构 pdf_三维温度场的重构方法,更准确地监测储能系统的电池堆内部温度

储能系统是微电网的核心组成部分,其热管理对于微电网的安全与稳定具有重要意义。相对于表面温度,电池堆内部温度场更有意义。针对红外热像仪无法监测电池堆内部温度场的问题,浙江工业大学分布式能源与微网研究所、浙江工业大学机械工程学院的…

linux找不到光口,以太坊查看命令_求助 输入ifconfig命令 后看不到eth0但是有eth3和eth4-CSDN论坛_区块链百科...

Ⅰ 怎么查看 /etc/sysconfig/network-scripts/ifcfg-eth0在你的这串英文前面加个 cat 空格就行Ⅱ 在linux下如何通过命令查网卡配置在linux下通过命令查网卡配置的方法如下:1、首先在电脑上打开Linux系统,然后进入Linux系统的终端窗口。Ⅲ 为什么用命令e…

开发物体识别桌、_想用人工智能实现安全风险管控?快来试试EasyMonitor一站式视频监控开发平台...

随着 AI 技术的日益成熟,越来越多的传统企业都希望用 AI 能力升级原有的管理系统,进而智能化解决业务问题、提高人效。尤其在安全生产领域中,虽然视频监控的覆盖率逐年提升,但大多企业还在沿用人工抽检的方式对设备、区域、人员进…

pla3d打印材料密度_口腔修复体制作用3D打印金属粉末的成型工艺与性能控制要点概述...

在传统口腔修复体的制作过程中,制作工艺繁琐,制作周期长,加工过程中依赖人力操作,金属材料在制作过程中易发生变形,难以控制尺寸精度,使患者舒适度下降。而采用3D打印技术生产的修复体可根据患者自身进行定…

linux semaphore,在CentOS 7操作系统上安装Semaphore的方法

本文介绍在CentOS 7操作系统上安装Semaphore的方法,安装完后就可以使用Semaphore来管理Ansible Web UI了。一、安装MariaDB数据库和git 2.x参考文章1、安装MariaDB数据库参考文章2、安装git 2.x确认git版本:$ git --versiongit version 2.16.5二、安装An…