NIO(四)
时间:2021-07-27
本文章向大家介绍NIO(四),主要包括NIO(四)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
多人聊天客户端
服务端
public class Server {
private ServerSocketChannel servSocketChannel;
private Selector selector;
/**
* 初始化服务器
* */
public Server(){
try {
servSocketChannel = ServerSocketChannel.open();
servSocketChannel.socket().bind(new InetSocketAddress(7000));
selector = Selector.open();
//开启非阻塞模式
servSocketChannel.configureBlocking(false);
//注册serverSocketChannel
servSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 监听连接
* */
public void listen() {
while (true) {
Iterator<SelectionKey> keyIterator = null;
try {
//这里我们等待1秒,如果没有事件发生, 返回
if(selector.select(1000) == 0) { //没有事件发生
continue;
}
Set<SelectionKey> selectionKeys = selector.selectedKeys();
keyIterator = selectionKeys.iterator();
if(keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
//客户端连接
if(key.isAcceptable()) {
SocketChannel socketChannel = servSocketChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
System.out.println(socketChannel.getRemoteAddress() + "上线");
}
//读已就绪
if(key.isReadable()) {
readData(key);
}else{
System.out.println("等待处理");
}
}
} catch (Exception e) {
e.printStackTrace();
}
//当前的key 删除,防止重复处理
keyIterator.remove();
}
}
public void readData(SelectionKey selectionKey) {
SocketChannel channel = (SocketChannel)selectionKey.channel();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
try {
int read = channel.read(byteBuffer);
while (read > 0) {
String msg = new String(byteBuffer.array());
System.out.println(msg);
//转发
sendInfoToOtherClients(msg, channel);
byteBuffer.clear();
read = channel.read(byteBuffer);
}
} catch (Exception e) {
e.printStackTrace();
selectionKey.cancel();
}
}
private void sendInfoToOtherClients(String msg, SocketChannel channel) {
Set<SelectionKey> keys = selector.keys();
for (SelectionKey key : keys) {
SelectableChannel targetChannel = key.channel();
if(targetChannel instanceof SocketChannel && targetChannel != channel) {
SocketChannel socketChannel = (SocketChannel) targetChannel;
ByteBuffer wrap = ByteBuffer.wrap(msg.getBytes());
try {
socketChannel.write(wrap);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Server server = new Server();
server.listen();
}
}
客户端
public class Client {
private SocketChannel socketChannel;
private final String IP = "127.0.0.1";
private Selector selector;
private final int port = 7000;
private String username;
public Client() {
try {
socketChannel = SocketChannel.open(new InetSocketAddress(IP, port));
selector = Selector.open();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
username = socketChannel.getLocalAddress().toString().substring(1);
System.out.println(username + " is ok...");
} 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();
//得到一个Buffer
ByteBuffer 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();
}
}
//向服务器发送消息
public void sendInfo(String info) {
info = username + " 说:" + info;
try {
socketChannel.write(ByteBuffer.wrap(info.getBytes()));
}catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
//启动我们客户端
Client chatClient = new Client();
//启动一个线程, 每个3秒,读取从服务器发送数据
new Thread() {
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);
}
}
}
原文地址:https://www.cnblogs.com/steven158/p/15067775.html
- Open Judge 2750 鸡兔同笼
- POJ 1017 Packets
- Hadoop离线数据分析平台实战——380MapReduce程序优化Hadoop离线数据分析平台实战——380MapReduce程序优化
- 配置远程访问Jupyter+腾讯云超划算活动上车
- HDU 4256 The Famous Clock
- ZOJ 1403&&HDU 1015 Safecracker【暴力】
- Torch7搭建卷积神经网络详细教程
- 爬虫入门到精通-HTTP协议的讲解
- 批量替换文件名和文本文件内容mac
- 抓取手机app的数据(摩拜单车)
- Hadoop离线数据分析平台实战——520项目总结Hadoop离线数据分析平台实战——520项目总结
- 爬虫入门到精通-mongodb的基本使用
- 拒绝撕逼,用数据来告诉你选择器到底哪家强
- 爬虫入门到精通-headers的详细讲解(If-modified-since)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- flutter中build.gradle仓库的配置(解决外网下载速度过慢失败的问题)
- Android studio 实现随机位置画10个随机大小的五角星的代码
- 详解Android Studio实现用户登陆界面demo(xml实现)
- Flutter 实现进度条效果
- Android 侧边滑动关闭Activity的示例代码
- Flutter 系统是如何实现ExpansionPanelList的示例代码
- Flutter中如何使用WillPopScope的示例代码
- Android实现音乐播放进度条传递信息的两种方式(在service和activity中)
- Flutter 中 Dart的Mixin示例详解
- Android Studio 实现九宫格功能
- Android user版通过adb_enable开启adb 调试 不提示对话框的流程分析
- Android实现圆线按钮进度效果
- Flutter 透明状态栏及字体颜色的设置方法
- Android实现带有进度条的按钮效果
- Android 自定义View实现多节点进度条功能