简易版多人聊天室——NIO

本地部署 Chat Nio 阅读详情

基于NIO的多人聊天室java

客户端

package com.yc.chat.nio;

import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Label;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
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.Set;

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Text;
 
import com.yc.chat.utils.ShowBoxUtil;
import com.yc.chat.utils.StringUtil;

import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem; 
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;

/**
*
* @author : 外哥
* 邮箱 : liwai2012220663@163.com
* 创建时间:2020年12月21日 下午9:04:13
*/
public class Client implements Runnable {

	protected Shell shell;
	private Text text;
	private Text text_1;
	private Text text_2;
	private Table table;
	private Text text_4;
	private Text text_3; 
	 
	// 表格中当前用户的昵称
	private TableItem tItem;
	// 存储昵称
	private String nickName = null ;
	// 判断是否连接
	private boolean connected = false ;
	// 线程
	private Thread th = null ;
	// 发送的消息
	private String msg = null ;
	// 客户端channel
	private SocketChannel socketChannel;
	private Selector selector;
	

	/**
	 * Launch the application.
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			Client window = new Client();
			window.open();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * Open the window.
	 */
	public void open() {
		Display display = Display.getDefault();
		createContents();
		shell.open();
		shell.layout();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
	}

	/**
	 * Create contents of the window.
	 */
	protected void createContents() {
		shell = new Shell();
		shell.setSize(1111, 763);
		shell.setText("源辰聊天室");
		shell.setLayout(null);
		
		Label label = new Label(shell, SWT.NONE);
		label.setBounds(78, 35, 76, 20);
		label.setText("服务器地址");
		
		Label label_1 = new Label(shell, SWT.NONE);
		label_1.setText("服务器端口");
		label_1.setBounds(341, 35, 76, 20);
		
		Label label_2 = new Label(shell, SWT.NONE);
		label_2.setBounds(609, 35, 50, 20);
		label_2.setText("昵称");
		
		text = new Text(shell, SWT.BORDER);
		text.setText("127.0.0.1");
		text.setBounds(176, 32, 121, 26);
		
		text_1 = new Text(shell, SWT.BORDER);
		text_1.setText("8000");
		text_1.setBounds(435, 32, 121, 26);
		
		text_2 = new Text(shell, SWT.BORDER);
		text_2.setText("李外");
		text_2.setBounds(665, 32, 84, 26);
		
		text_3 = new Text(shell, SWT.BORDER | SWT.WRAP | SWT.V_SCROLL | SWT.MULTI);
		text_3.setBounds(78, 97, 671, 484);
		
		Button button = new Button(shell, SWT.NONE);
		
		
		button.setBounds(821, 17, 237, 56);
		button.setText("登录");
		
		table = new Table(shell, SWT.BORDER);
		table.setBounds(821, 97, 237, 484);
		table.setHeaderVisible(true);
		
		TableColumn column = new TableColumn(table, SWT.NONE);
		column.setText("在线用户");
		column.setWidth(236);
		
		text_4 = new Text(shell, SWT.BORDER | SWT.WRAP | SWT.V_SCROLL | SWT.MULTI);
		text_4.setBounds(78, 606, 671, 78);
		
		Button btnNewButton = new Button(shell, SWT.NONE); 
		btnNewButton.setBounds(821, 606, 237, 78);
		btnNewButton.setText("发送");
		
		
		/**
		 * 登录按钮的点击事件
		 */
		button.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				
				if ( connected == true ) {
					ShowBoxUtil.showMessageBox(shell, "已经登录", "提示");
					return ;
				}
				
				// 连接服务器
				connect();
				
				// 如果连接成功,则启用一个线程,随时等待服务器端发过来的消息
				th = new Thread( Client.this ) ;
				th.start(); 
				
			}
		});  
		
		/**
		 *  发送消息按钮的点击事件
		 */
		btnNewButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				
				String content = text_4.getText().trim() ;
				
				try {
					// 如果要发送的消息为null,则提示信息
					if ( StringUtil.checkNull( content)) {
						ShowBoxUtil.showMessageBox(shell, "消息不能为空", "提示");
						return ;
					}
					
					// 否则发送消息
					content = "info#" + nickName + "说:\n" + content ;
					
					// 将消息写入channel中
					socketChannel.write( Charset.forName("UTF-8").encode(content)) ;
					
					text_4.setText("");
				} catch (Exception e1) {
					e1.printStackTrace();
				}
				 
			}
		}); 
	}

	/**
	 * 连接服务器的方法
	 */
	private void connect() {
		String ip = text.getText().trim() ;
		int port = Integer.parseInt( text_1.getText().trim() ) ;
		
		try { 
			// 连接服务器
			socketChannel = SocketChannel.open( new InetSocketAddress( ip , port )) ;
			
			System.out.println( "成功连接" + ip );
			
			// 设置channel为非阻塞式
			socketChannel.configureBlocking( false ) ;
			
			selector = Selector.open() ;
			
			// 注册channel的 可读 监听事件
			socketChannel.register(selector, SelectionKey.OP_READ ) ;
			
			nickName = text_2.getText().trim() ;
			connected = true ;
			
			// 向服务器发送消息
			socketChannel.write( Charset.forName("UTF-8").encode("login#" + nickName )) ;
			 
		}  catch (Exception e) {
			connected = false ;
			e.printStackTrace();
		}  
	}

	@Override
	public void run() {
		try {
			// 6.循环等待处理监听事件
			while ( true ) {
				
				// 获取可用的channel数量
				int readyChannels = selector.select();
				
				if ( readyChannels == 0 ) {
					// 如果可用的数量为0,则开始下一次循环
					continue ;
				}
				
				// 否则获取可用的channel集合
				Set<SelectionKey> selectedKeys = selector.selectedKeys();
				
				// 获取这个集合的迭代器
				Iterator<SelectionKey> iterator = selectedKeys.iterator();
				
				/**
				 * 对集合中的所有事件进行处理
				 */
				while ( iterator.hasNext() ) {
					// 获取SelectionKey实例
					SelectionKey selectionKey = iterator.next();
					
					// 移除当前集合中的SelectionKey
					iterator.remove();
					
					// 7.根据就绪的状态,调用相应的处理逻辑 
					if ( selectionKey.isReadable() ) {
						// 如果是可读事件
						readHandler(selectionKey, selector);
					}
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		} 
	} 
	
	/**
	 * 可读事件处理器
	 * @throws IOException 
	 */
	private void readHandler( SelectionKey selectionKey , Selector selector ) throws IOException {
		// 先获取此可读事件的channel
		SocketChannel socketChannel = (SocketChannel) selectionKey.channel() ;
		 
		// 创建buffer,并指定大小
		ByteBuffer byteBuffer = ByteBuffer.allocate( 1024 ) ;
		
		// 循环读取服务器channel中的内容
		msg = "" ;
		while ( socketChannel.read( byteBuffer) > 0 ) {
			// 切换buffer为读模式 
			byteBuffer.flip() ;
			
			// 通过UTF-8方式解码
			msg += Charset.forName("UTF-8").decode( byteBuffer ) ;
			
		}
		
		System.out.println( msg );
		
		// 将channel重新加入selector中,监听可读事件
		socketChannel.register( selector , SelectionKey.OP_READ ) ;
		
		// 将服务器响应的消息打印到本地 
		if ( msg.startsWith("info#")) {
			// 聊天消息
			Display.getDefault().asyncExec( new Runnable() {
				
				@Override
				public void run() {
					text_3.append( "\n" + msg.replaceFirst("info#", ""));
				}
			});
		}else if ( msg.startsWith("login#")) {
			// 登录信息
			Display.getDefault().asyncExec(new Runnable() {
				
				@Override
				public void run() {
					tItem = new TableItem(table, SWT.None) ;
					tItem.setText( msg.replaceFirst("login#", ""));
				}
			}); 
		}
	}
}

服务器端

package com.yc.chat.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.Channel;
import java.nio.channels.Pipe.SourceChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set; 

/**
*
* @author : 外哥
* 邮箱 : liwai2012220663@163.com
* 创建时间:2020年12月30日 下午5:22:02
*/
@SuppressWarnings("all")
public class NIOServer {
	
	private boolean connected = false ;
	/**
	 * 主方法
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		NIOServer server = new NIOServer() ;
		server.start();
	}
	
	/**
	 * 启动方法
	 * @throws IOException 
	 */
	public void start() throws IOException {
		// 1.创建Selector
		Selector selector = Selector.open() ;
		
		// 2.创建channel通道
		ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
		
		// 3.为channel通道绑定监听端口
		serverSocketChannel.bind( new InetSocketAddress(8000) ) ;
		
		// 4.将channel设置为非阻塞模式
		serverSocketChannel.configureBlocking( false ) ;
		
		// 5.将channel注册到selector中,监听接入事件
		serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT) ;
		// 打印日志信息
		System.out.println("服务器启动成功,占用端口8000");
		connected = true ;
		
		// 6.循环等待处理监听事件
		while ( true ) {
			
			// 获取可用的channel数量
			int readyChannels = selector.select();
			
			if ( readyChannels == 0 ) {
				// 如果可用的数量为0,则开始下一次循环
				continue ;
			}
			
			// 否则获取可用的channel集合
			Set<SelectionKey> selectedKeys = selector.selectedKeys();
			
			// 获取这个集合的迭代器
			Iterator<SelectionKey> iterator = selectedKeys.iterator();
			
			/**
			 * 对集合中的所有事件进行处理
			 */
			while ( iterator.hasNext() ) {
				// 获取SelectionKey实例
				SelectionKey selectionKey = iterator.next();
				
				// 移除当前集合中的SelectionKey
				iterator.remove();
				
				// 7.根据就绪的状态,调用相应的处理逻辑
				if ( selectionKey.isAcceptable() ) {
					// 如果是客户端接入事件
					acceptHandler(serverSocketChannel, selector);
				}
				
				if ( selectionKey.isReadable() ) {
					// 如果是可读事件
					readHandler(selectionKey, selector);
				}
			}
		} 
	}
	
	/**
	 * 接入事件处理器
	 * @throws IOException 
	 */
	private void acceptHandler( ServerSocketChannel serverSocketChannel,
								Selector selector) 
					throws IOException {
		
		// 获取链接的客户端channel
		SocketChannel socketChannel = serverSocketChannel.accept();
		
		// 将socketchannel设置为非阻塞
		socketChannel.configureBlocking( false );
		
		// 将socketchannel注册到selector上,监听可读事件
		socketChannel.register(selector, SelectionKey.OP_READ) ;
		
		// 回复客户端提示信息,通过UTF-8方式编码
//		socketChannel.write( Charset.forName("UTF-8").encode("请注意隐私安全")) ; 
	}
	
	/**
	 * 可读事件处理器
	 * @throws IOException 
	 */
	private void readHandler( SelectionKey selectionKey , Selector selector ) throws IOException {
		// 先获取此可读事件的channel
		SocketChannel socketChannel = (SocketChannel) selectionKey.channel() ;
		 
		// 创建buffer,并指定大小
		ByteBuffer byteBuffer = ByteBuffer.allocate( 1024 ) ;
		
		// 循环读取客户端channel中的内容
		String request = "" ;
		while ( socketChannel.read( byteBuffer) > 0 ) {
			// 切换buffer为读模式 
			byteBuffer.flip() ;
			
			// 通过UTF-8方式解码
			request += Charset.forName("UTF-8").decode( byteBuffer ) ;
			
		}
		
		// 将channel重新加入selector中,监听可读事件
		socketChannel.register( selector , SelectionKey.OP_READ ) ;
		 
		// 如果是登录信息,则获取昵称
//		if ( request.startsWith("login#")) {
//			//request = request.replaceFirst("login#", "") ;
//		}

		// 发送群聊消息,将消息发送给每一个连接上这个服务器的人
		// 将客户端发送的信息广播给其他的用户
		if ( request.length() > 0 ) {
			System.out.println( request );
			broadCast( selector , socketChannel , request ); 
		}
		
		// 说明是下线消息
		if ( request.startsWith("exit#")) { 
			this.connected = false ;
		} 
	}
	
	/**
	 * 广播方法
	 */
	private void broadCast( Selector selector , SocketChannel  sourceChannel , String request) {
		
		/**
		 * 获取所有的客户端channel
		 */
		Set<SelectionKey> selectionKeys = selector.keys();
		
		/**
		 * 给所有的客户端channel发送消息
		 */
		selectionKeys.forEach( selectionKey -> {
			// 获取客户端channel
			Channel socketChannel = selectionKey.channel() ;
			
			// 如果这个channel是客户端channel,则发送消息
			if ( socketChannel instanceof SocketChannel) {
				try {
					((SocketChannel) socketChannel).write( Charset.forName("UTF-8").encode( request )) ;
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		});
		
	}
	
}

总结:从整个开发过程中,对nio的使用流程和规律有了一定的掌握。通过对比nio和bio发现,bio的使用简单,但开启的线程数过多,占用资源,而nio拓展出了一个对线程事件的管理机制,有效的解决了bio的弊端。

Netty :Netty介绍 & 实现简易多人聊天室 Netty :Netty介绍 & 实现简易多人聊天室 博主在去年二月份就介绍了Java原生网络编程API,并用它们实现了多种I/O模型的简易多人聊天室: Java网络编程-Socket编程初涉一(简易客户端-服务器) Java网络编程-Socket编程初涉二(基于BIO模型的简易多人聊天室) Java网络编程-Socket编程初涉三(伪异步I/O模型的简易多人聊天室) Java网络编程-Socket编程初涉四(NIO模型的简易多人聊天室) Java网络编程-Socket编程初涉五 阅读详情

相关推荐

java NIO及NIO聊天室

参考链接: java NIO实例1:http://blog.chinaunix.net/uid-25808509-id-3346228.html java NIO教程之selector(一系列):http://ifeve.com/selectors/ java NIO与IO的比较:http://blog.youkuaiyun.com/keda8997110/article/details/19549

lh87522的专栏 2066

探索未来对话的无限可能:Chat Nio AI聚合聊天平台全面解析

在人工智能技术飞速发展的今天,如何高效整合各类AI模型成为众多开发者和企业面临的挑战。**Chat Nio**作为一款强大的AI聚合聊天平台,为这一难题提供了完美的解决方案。这款开源项目支持OpenAI、Claude、讯飞星火、Midjourney、Stable Diffusion等主流模型,实现了真正的**一站式AI对话体验**。 ## 🚀 什么是Chat Nio? **Chat Nio*

gitblog_00272的博客 2551

NioChat:一个使用 Java NIO 的简单聊天应用程序

蔚来 我在课程中用 Java NIO 做的一个项目作为作业 任务 服务器和客户端架构 - 可以同时连接多个客户端 客户端通过用户名和密码进行身份验证 - 每个用户名都是唯一的,一次只能由一个客户端使用 来自用户 a 的消息发送给所有其他连接的用户,而发件人则从服务器接收状态消息 客户端可以上传和下载文件 客户端可以查看当前上传到服务器的所有文件的列表(通过键入“/fileList”) 工具 JDK 1.8 智能 IDEA 14

被数百万元收购的 ChatNio 初体验

最近一则新闻 15 岁山东初中生做 CTO,开源项目刚刚被数百万元收购了 火爆出圈,笔者看了下被收购的开源项目 ChatNio,发现挺好用了,就体验下。ChatNio 号称下一代 AIGC 一站式商业解决方案,其功能融合了 Next Web 和 One API 各自的优点,通过整合实现 1+1>2 的效果:Chat Nio > Next Web + One APIChatNio 在保持...

机器学习与系统 2839

Chat:Java NIO+多线程实现聊天室

Java基于多线程和NIO实现聊天室 涉及到的技术点 线程池ThreadPoolExecutor 阻塞队列BlockingQueue,生产者消费者模式 Selector Channel ByteBuffer ProtoStuff 高性能序列化 HttpClient连接池 Spring依赖注入 lombok简化POJO开发 原子变量 内置锁 CompletionService log4j+slf4j日志 实现的功能 登录注销 单聊 群聊 客户端提交任务,下载图片并显示 上线下线公告 在线用户记录 批量下载豆瓣电影的图片,并打为压缩包传输给客户端 客户端使用方式: 登录:默认用户名是user1-user5,密码分别是pwd1-pwd5 例:打开客户端后输入用户名为user1,密码为pwd1 注销:关闭客户端即可 单聊:@username:message 例:@user2:hello 群聊:me

NVIDIA 2025 Board Design Engineer 校招笔试

电路分析,矩形波阶跃反馈驱动​,误差信号。非常简单,数电or​离散基础。第一题是考试规矩知情确认。大二暑假做的,纯体验​。五六题太长,下篇分享。

m0_74253823的博客 1131

Java 用NIO实现一个聊天室(多人聊天、单人聊天)

这两行代码由于前后发送,所以client这个channel会先后收到 昵称验证通过 和 推送上线 的消息,如果tcp在传输过程中足够快,那么客户端在一次read事件中,会把两次消息一次性读出来。而由于这个代码写的比较简陋,在tcp的传输内容上并没有建立起足够安全的内容协议(比如消息与消息用特定的分隔符、或者用前面的几个字节来标注内容的实际字节数),所以上述代码并不能两次消息分开了。 造成的问题是:客户端是通过服务端回复的 验证消息 来初始化姓名的,如果粘包情况出现,那么客户端将会把真正的姓名和上线消息合起

anlian523的博客 2327

HWDB1.1数据集处理全攻略:从gnt文件到PNG图片的完整转换教程

本文提供了HWDB1.1数据集处理的完整教程,详细解析了gnt二进制文件格式,并给出了从文件解析、标签映射到批量转换为PNG图片的Python脚本。教程涵盖了环境准备、跨平台解压方案,以及为PyTorch等深度学习框架准备数据的最佳实践,是进行手写汉字识别研究不可或缺的实用指南。

2w3e4r5t6y的博客 632

NIO实现多人聊天室

1. 前言 首先对应NIO来说是同步非阻塞的,这里再看一下什么是同步什么是异步,什么是阻塞什么是非阻塞 ① 同步VS异步 同步 同步和异步关注的是消息通信机制,所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了 换句话说,就是由调用者主动等待这个调用的结果 异步 而异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一...

Javaer`s blog 339

Aurora 8B/10B IP核介绍 —— Xilinx 技术文档Pg046

一、概述该IP核与用户接口之间支持AXI4-Stream协议,且基于ZYNQ SOC、A7、K7、V7以及UltraScale、UltraScale+系列FPGA的高速收发器(the high-speed serial transceivers)进行实现。多达 16 个连续绑定4 个连续绑定的 GTP 收发器framingstreaming以及全双工或单工加扰消扰CRC校验热插拔Aurora 8B/10B核心(图1-1)是一种可扩展的、轻量级的、用于高速串行通信的链路层协议;

qq_32147275的博客 1640

YOLOv13+SAHI实战:5步搞定无人机航拍小目标检测(附VisDrone数据集调参技巧)

本文详细介绍了如何结合YOLOv13与SAHI(切片辅助超推理)技术,在VisDrone2019数据集上实现高效的无人机航拍小目标检测。通过5个实战步骤,包括环境配置、SAHI参数解析、数据集调优、完整训练推理流程和性能优化技巧,帮助开发者显著提升小目标检测的准确率和效率。

egg99的博客 431

NIO网络编程实战之简单多人聊天室

NIO网络编程实战 利用NIO编程知识,实现多人聊天室。 1. NIO编程实现步骤 第一步:创建Selector 第二步:创建ServerSocketChannel,并绑定监听端口 第三步:将Channel设置为非阻塞模式 第四步:将Channel注册到Selector上,监听连接事件 第五步:循环调用Selector的select方法,检测就绪情况 第六步:调用selectedKeys方法获取就...

一只特立独行的猪 765

28-基于STM32单片机的便携式健康监测系统设计与实现(程序+原理图+元件清单)

本文详细介绍了基于STM32单片机的便携式健康监测系统设计与实现,该系统集成MAX30102光电传感器和MSP20压力传感器,实时监测心率、血氧和血压等关键生理指标。通过STM32F103C8T6主控芯片和HC-05蓝牙模块,实现数据采集、处理及无线传输,具有便携性高、操作简便等特点,适用于家庭健康监护和户外运动场景。

weixin_29191669的博客 420

Java网络编程-Socket编程初涉四(NIO模型的简易多人聊天室)

Java网络编程-Socket编程初涉四(NIO模型的简易多人聊天室) 什么是NIO模型呢? Java网络编程-NIO原理 之前版本 Java网络编程-Socket编程初涉三(伪异步I/O模型的简易多人聊天室) 服务器 这里使用Channel、Selector、Buffer来实现一个NIO模型的服务器,服务器的主要逻辑如下: 首先创建ServerSocketChannel(服务器管道),拿到关于...

kaven 1351

别再只会用Excel了!Minitab 21手把手教你搞定SPC控制图(从数据导入到结果解读)

本文详细介绍了如何使用Minitab 21高效制作SPC控制图,从数据导入到结果解读的全流程。通过对比Excel的局限性,展示Minitab在自动化计算、图表标准化和特殊原因检验等方面的优势,帮助质量管理人员提升工作效率和数据分析专业性。

weixin_30878501的博客 386

YOLOv11缝合添加注意力机制:添加YOLO-Face的SEAM到并行通道空间注意力机制【附代码】

在目标检测的实际应用中,物体遮挡是一个严重影响检测精度的难点。本文将基于YOLOv11架构,探索融合YOLO-Face中提出的SEAM注意力机制以提升对遮挡物体的感知能力,并在此基础上提出一种轻量化双路径并行注意力机制C2PSA,进一步提升检测性能。

一键难忘的博客 1530

Java 实现的多人网络聊天室

Java 实现的多人网络聊天室 Author : ScorpioDong 1. 成品展示 2. 软件界面的绘制 Java可用的GUI框架有AWT,Swing、JavaFX等,JavaFX是Java推荐使用的较大型的GUI框架,界面拥有很高的可定制性。因为本软件功能较少,以学习网络通信为目的,所以使用简单易上手的Swing框架。 这里新建了一个MainFrame的类,继承自JFrame,实现软...

m0_37771142的博客 4928

【信息系统项目管理师】第1章:信息化发展 考点梳理

本文主要详细梳理高项:信息化、新型基础设施建设、两化融合、数字中国、数字化转型与元宇宙等内容。

数据知道的博客 8591

JAVA网络编程NIO实现简易多人聊天室

BIO模型 BIO即blocking IO,顾名思义是一种阻塞模型。当没有客户端连接时,服务端会一直阻塞,当有客户端新建连接时,服务端会新开一个线程去响应(不用多线程的话服务端同一时刻最多只能接收一个连接)。但不断的新开线程对服务器的压力是巨大的,为了缓解压力可以采用线程池技术实现线程复用,但这种做法治标不治本,本质还是一个连接一个线程。代码如下: //服务端 public class BIOServer { private final static int PORT = 8888; p

qq_40246487的博客 1512

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

多人聊天室 NIO模型实现

使用Channel代替Stream使用Selector监控多条Channel可以在一个线程里处理多个Channel I/O。

m0_62112384的博客 834

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

【Java】基于NIO的多人聊天室

前言 学习了NIO的基本原理及使用方法之后,开始尝试写一个NIO实现的聊天室,练习一下代码流程。 服务器端 服务器端主要负责接受各客户端的连接,接收客户端发来的信息,并且将其广播给所有已连接客户端。 /** * Created by makersy on 2019 */ /** * NIO服务器端 */ public class NioServer { /** * 启...

makersy的博客 472

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

利用NIO实现多人聊天室

java NIO 多人聊天室

m0_64208453的博客 253

NIO实现多人聊天室(java)

多人聊天室服务端代码 package com.xjb.nio.chatroom; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.*; import java.nio.charset.Charset; import...

未来的那个你 292

创建NIO多人聊天室

限制BIO多人聊天室的性能的主要原因是因为 阻塞IO的存在 ,所以使用 非阻塞IO 阻塞io线程的消耗: 当没有客户端到达时,accept()处于阻塞状态, 但是有客户端到达时,会从阻塞状态 变成 执行状态,会得到一个socket。 这时 会将 socket 的 inputstream 和 output stream 转换成两个线程 或 一个读线程 和 一个单线程池(用于写入) 所以 当有 n个客户端连接时,线程数量会大于 2n。 线程的rea...

迷路人的博客 241

分别使用netty和Java nio 和 websocket 实现多人聊天室

Netty 是一款异步的事件驱动的网络应用程序框架,支持快速地开发可维护的高性能的面向协议的服务器和客户端。 Java nio : 新的还是非阻塞的NIO 最开始是新的输入/输出(New Input/Output)的英文缩写,但是,该Java API 已经出现足够长的时间了,不再是“新的”了,因此,如今大多数的用户认为NIO 代表非阻塞 I/O(Non-blocking I/O),而阻塞I/O(b...

newVenues的专栏 1153

Java 输入与输出之 NIO【NIO网络编程】探索之【五】【Selector详解】【多人聊天室例程】

NIO网络通讯程序【多人聊天室例程】,详细介绍了NIO的核心组件Selector和selectedKeys,selectedKeys它是通道Channel注册到Selector上的已注册的键的集合的子集。本文详细剖析了Selector选择器与通道相结合开发网络通讯程序的步骤,对Java网络通讯程序的开发有一定的参考价值。

weixin_42369079的博客 893
上一篇: Visual Studio连接Oracle数据库的连接字符串报错
下一篇: 自定义简易版tomcat--基于网络编程
夕卜
博客等级 码龄6年 18粉丝 28原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值