nio 服务端:
package nio.study.serverclient;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Iterator;
public class EchoSelectorServer {
//缓存大小
private static final int BUFSIZE = 256;
//超时时间
private static final int TIMEOUT = 3000;
//端口
private static final int PORT = 8888;
public static void main(String[] args) throws IOException {
Selector selector = Selector.open();
ServerSocketChannel listnChannel = ServerSocketChannel.open();
listnChannel.socket().bind(new InetSocketAddress(PORT));
// 只有非阻塞信道才可以注册选择器,因此需要将其配置为适当的状态
listnChannel.configureBlocking(false);
// 在注册过程中指出该信道可以进行“accept”操作
listnChannel.register(selector, SelectionKey.OP_ACCEPT);
Protocol protocol = new EchoProtocol(BUFSIZE);
while (true) {
if (selector.select(TIMEOUT) == 0) {
continue;
}
Iterator<SelectionKey> keyIter =
selector.selectedKeys().iterator();
while (keyIter.hasNext()) {
SelectionKey key = keyIter.next();
System.out.println("isAcceptable:"+key.isAcceptable());
if (key.isAcceptable()) {
protocol.handleAccept(key);
}
/*if(!key.isConnectable()){
System.out.println("cancel.......");
key.cancel();
}*/
System.out.println("isReadable: "+key.isReadable());
if (key.isReadable()) {
protocol.handleRead(key);
}
// System.out.println("isWritable: "+key.isWritable()
// +";isValid="+key.isValid());
try{
if (key.isWritable() && key.isValid()) {
protocol.handleWrite(key);
}
}catch(Exception e){
e.printStackTrace();
key.cancel();
if(null != key.channel() && key.channel().isOpen()){
key.channel();
}
}
// 由于select()操作只是向Selector所关联的键集合中添加元素
// 因此,如果不移除每个处理过的键,
// 它就会在下次调用select()方法时仍然保留在集合中
// 而且可能会有无用的操作来调用它。
keyIter.remove();
}
}
}
}
package nio.study.serverclient;
import java.io.IOException;
import java.nio.channels.SelectionKey;
public interface Protocol {
public void handleAccept(SelectionKey key) throws IOException;
public void handleRead(SelectionKey key) throws IOException;
public void handleWrite(SelectionKey key) throws IOException;
}
package nio.study.serverclient;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
public class EchoProtocol implements Protocol {
private int bufsize;// 为每个客户端信道创建的缓冲区大小
public EchoProtocol(int bufsize) {
this.bufsize = bufsize;
}
public void handleAccept(SelectionKey key) throws IOException {
// channel()方法返回注册时用来创建的Channel,该Channel是一个ServerSocketChannel,
// 因为这是我们注册的唯一一种支持accept操作的信道,
// accept()方法为传入的连接返回一个SocketChannel实例。
SocketChannel channel = ((ServerSocketChannel) key.channel()).accept();
// 这里无法注册阻塞式信道,必须是非阻塞式的
channel.configureBlocking(false);
// 可以通过SelectionKey类的selector()方法来获取相应的Selector。
// 我们根据指定大小创建了一个新的ByteBuffer实例,
// 并将其作为参数传递给register()方法。它将作为附件,与regiter()方法所返回的
// SelectionKey实例相关联。
channel.register(key.selector(), SelectionKey.OP_READ, ByteBuffer
.allocateDirect(bufsize));
}
public void handleRead(SelectionKey key) throws IOException {
// 根据其支持数据读取操作可知,这是一个SocketChannel。
SocketChannel channel = (SocketChannel) key.channel();
// 建立连接后,有一个ByteBuffer附件加到该SelectionKey实例上,这个附件里面的内容将
// 会在发送的时候用到,附件始终是附着这个长连接上
ByteBuffer buf = (ByteBuffer) key.attachment();
long bytesRead = channel.read(buf);
// System.out.println("data::"+ new
// String(buf.array(),0,(int)bytesRead));
// 如果read()方法返回-1,则表示底层连接已经关闭,此时需要关闭信道。
// 关闭信道时,将从选择器的各种集合中移除与该信道关联的键。
if (bytesRead == -1) {
channel.close();
} else if (bytesRead > 0) {
// 将缓冲区当前的limit设置为position=0,用于后续对缓冲区的读取操作
buf.flip();
// 根据缓冲区可读字节数创建字节数组 //buf.remaining() 可读取长度
byte[] bytes = new byte[buf.remaining()];
// 将缓冲区可读字节数组复制到新建的数组中
buf.get(bytes);
String expression = new String(bytes, "UTF-8");
System.out.println("服务器收到消息:" + expression);
// 处理数据
buf.clear();
// 这里依然保留了信道的可读操作,虽然缓冲区中可能已经没有剩余空间了,
key.interestOps(SelectionKey.OP_WRITE);
}
}
public void handleWrite(SelectionKey key) throws IOException {
System.out.println("======write---");
// 附加到SelectionKey上的ByteBuffer包含了之前从信道中读取的数据。
// 读取客户端的数据 begin
//ByteBuffer buf = (ByteBuffer) key.attachment();
// 该方法用来修改缓冲区的内部状态,以指示write操作从什么地方获取数据,及还剩多少数据
// buf.flip();
//////// end
String back = "99999server1234567890123456789123456789=99999999999999999999=qwertyuioplkjhgfdsazxcvbnmend";
back =back+back+back;
// 将消息编码为字节数组
byte[] bytes = back.getBytes();
// 根据数组容量创建ByteBuffer
ByteBuffer buf2 = ByteBuffer.allocate(bytes.length);
buf2.clear();
// 将字节数组复制到缓冲区
buf2.put(bytes);
// flip操作 ,从缓冲的0位置开始写
buf2.flip();
System.out.println("======write---2");
System.out.println("write:" + new String(bytes));
SocketChannel channel = (SocketChannel) key.channel();// 获取信道
if(buf2.hasRemaining()){
int len =channel.write(buf2);// 向信道中写数据
System.out.println("len:"+len);
}
if(null !=channel){
channel.close();
}
}
}
客户端:
package nio.study.serverclient;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
public class TCPEchoClientNoblocking {
public void send(int i) throws Exception{
String server = "127.0.0.1";
String mgs = i+"1234567890qwertyuiopasdfghjklmnbvcxzqwertyuiopasdfghjklmnbvcxz";
byte[] data = mgs.getBytes();
int servPort = 8888;
SocketChannel clntChan =SocketChannel.open();
clntChan.configureBlocking(false);
//我们通过持续调用finishConnect()方法来“轮询”连接状态,该方法在连接成功建立之前
//一直返回false。打印操作显示了在等待连接建立的过程中,程序还可以执行其他任务
if (!clntChan.connect(new InetSocketAddress(server,servPort))) {
while (!clntChan.finishConnect())
}
}
ByteBuffer writeBuf =ByteBuffer.wrap(data);
ByteBuffer readBuf =ByteBuffer.allocate(data.length);
int bytesRcvd =0;
int topNum =0;
StringBuffer sb = new StringBuffer(64);
while (bytesRcvd >= topNum) {
if (writeBuf.hasRemaining()) {
clntChan.write(writeBuf);
}
topNum = bytesRcvd;
bytesRcvd =clntChan.read(readBuf);
//
readBuf.flip();
if(bytesRcvd >0){
sb.append(new String(readBuf.array(), 0,readBuf.limit()));
System.out.println("len;;;"+bytesRcvd +readBuf.hasRemaining());
}
readBuf.clear();
}
System.out.println("rev::"+sb.toString());
clntChan.close();
}
public static void main(String[] args) throws Exception {
for(int i=0;i<300;i++){
TCPEchoClientNoblocking t = new TCPEchoClientNoblocking();
t.send(i);
}
}
}
日志:
服务端:
isAcceptable:true
isReadable: false
isAcceptable:false
isReadable: true
服务器收到消息:295ABCDEFGHIJKLMNOPQRSTUVWXYZ789564559
isAcceptable:false
isReadable: false
======write---
======write---2
write:99999server1234567890123456789123456789=99999999999999999999=qwertyuioplkjhgfdsazxcvbnmend99999server1234567890123456789123456789=99999999999999999999=qwertyuioplkjhgfdsazxcvbnmend99999server1234567890123456789123456789=99999999999999999999=qwertyuioplkjhgfdsazxcvbnmend
len:270
isAcceptable:true
isReadable: false
isAcceptable:false
isReadable: true
服务器收到消息:296ABCDEFGHIJKLMNOPQRSTUVWXYZ789564559
isAcceptable:false
isReadable: false
======write---
======write---2
write:99999server1234567890123456789123456789=99999999999999999999=qwertyuioplkjhgfdsazxcvbnmend99999server1234567890123456789123456789=99999999999999999999=qwertyuioplkjhgfdsazxcvbnmend99999server1234567890123456789123456789=99999999999999999999=qwertyuioplkjhgfdsazxcvbnmend
len:270
客户端:
len;;;38true
len;;;38true
len;;;38true
len;;;38true
len;;;38true
len;;;38true
len;;;38true
len;;;4true
rev::99999server1234567890123456789123456789=99999999999999999999=qwertyuioplkjhgfdsazxcvbnmend99999server1234567890123456789123456789=99999999999999999999=qwertyuioplkjhgfdsazxcvbnmend99999server1234567890123456789123456789=99999999999999999999=qwertyuioplkjhgfdsazxcvbnmend
相关推荐
Java SpringBoot 整合Mina框架,涉及到的核心技术主要包括Java NIO(非阻塞I/O)、Mina框架以及SpringBoot的集成应用。本教程旨在帮助开发者深入理解和掌握这些技术,并提供了一个可直接使用的基础平台框架。 Java ...
Java作为一门广泛使用的开发语言,提供了多种I/O(Input/Output)通信模型,包括传统的阻塞I/O(BIO)、非阻塞I/O(NIO)以及异步I/O(AIO)。这些通信模型在不同的场景下有着各自的优势,理解和掌握它们对于优化...
在本教程中,我们将深入探讨如何整合Spring Boot与Mina框架,同时介绍Java NIO(非阻塞I/O)的基础知识。Spring Boot以其简洁、快速的起步方式深受开发者喜爱,而Mina则是一个强大的网络通信框架,常用于构建高性能...
本文将深入探讨Java中的三种主要通讯模型:BIO( Blocking I/O)、NIO(Non-blocking I/O)和AIO(Asynchronous I/O),并结合实际的代码示例进行综合演练。 **一、BIO(阻塞I/O)** 1. **概念**:BIO是Java早期的...
netty 使用 4.0 jar 包 免费分享
**JAVA NIO 异步通信模板服务端** Java NIO(New Input/Output)是Java在J2SE 1.4版本中引入的一个新特性,它提供了与标准I/O完全不同的编程模型,尤其是在处理大量并发连接时,NIO展现出了更高的效率。本模板...
### Java NIO通信框架在电信领域的实践 #### 华为电信软件技术架构演进 **1.1 电信软件概述** 电信软件是一个宽泛的概念,根据功能和应用场景的不同大致可以分为两大类:系统软件和业务应用软件。系统软件通常...
NIO(Non-blocking I/O,非阻塞I/O)是Java平台中的一种I/O模型,与传统的BIO(Blocking I/O,阻塞I/O)相比,NIO在处理高并发、大数据传输时表现出更高的效率和更好的性能。NIO的核心概念包括通道(Channel)、缓冲...
Ioserver java Nio socket 框架 是个不错的NIO 通讯框架,本来想学习mina框架,看了看mina的源码太头痛,本人觉得看懂了Ioserver 再看mina的框架,想多的学习 java NIO 的也可以下载 看看,很值得学习啊!!!
Nacos的通讯原理及Netty的NIO通讯 Nacos(命名与配置服务)作为一个服务发现与配置管理基础设施,其核心通讯机制依赖于Netty的NIO技术。Netty是一个高性能、异步事件驱动的网络应用框架,它使得开发健壮的服务端和...
用java编写的nio通信的例子,nio是io编程的新版本,比io较流行。同时本例子是适用socket通信的。可以在此基础上,添加您的个人应用。本例子适用于:java通信的学习者,android平台通信的学习者。
Gecko是一个Java NIO的通讯组件,它在一个轻量级的NIO框架的基础上提供了更高层次的封装和功能。支持的RPC调用方式包括RR(request-response)和pipeline 特性: 可插拔的协议设计 连接池 分组管理和负载均衡 ...
标题中的“3种下载文件程序的思考,为何使用NIO进行异步网络通讯”提示了我们探讨的主题,即网络通信中的不同下载策略以及为何选择非阻塞I/O(Non-blocking I/O, NIO)作为异步通信的方式。在这个话题中,我们将深入...
在这个Java NIO IM(即时通讯)服务器和客户端的示例中,我们将探讨如何利用NIO进行双向通信,并理解其背后的机制。 1. **NIO基础概念** - **通道(Channel)**:在NIO中,数据是通过通道进行传输的。通道类似于流...
Tomcat7调优主要包括禁用不必要的AJP协议、切换到更高效的NIO通讯模式以及合理配置JVM参数。这些步骤有助于减少资源消耗,提高并发处理能力,从而提升整体系统性能。同时,持续监控和调整是保持Tomcat高效运行的关键...
首先,Dubbo的核心组件之一是高性能的NIO通讯机制。NIO(Non-blocking I/O)允许在单个线程中处理多个连接,大大提高了服务器处理并发请求的能力。Dubbo通过实现NIO,提供了高效的网络通信能力,确保了服务间的快速...
### JAVANIO在Socket通讯中的应用 #### 引言 在Java开发中,网络通信是常见需求之一,其中Socket编程是最基础也是最重要的技术之一。然而,在传统的Java Socket编程中,由于采用的是阻塞I/O模型,即所有的读写操作...
### NIO系列DATASHEET.pdf知识点总结 #### 一、NIO系列产品概述 **NIO系列DATASHEET.pdf**提供了NIO系列产品的详细介绍和技术规格,该文档覆盖了多个型号的产品,包括不同类型的输入输出模块、电源设备以及网络...