`

nio 通讯

    博客分类:
  • java
 
阅读更多

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 框架,nio通讯基础教程,mina框架基础教程.zip

    Java SpringBoot 整合Mina框架,涉及到的核心技术主要包括Java NIO(非阻塞I/O)、Mina框架以及SpringBoot的集成应用。本教程旨在帮助开发者深入理解和掌握这些技术,并提供了一个可直接使用的基础平台框架。 Java ...

    基于java的BIO、NIO、AIO通讯模型代码实现

    Java作为一门广泛使用的开发语言,提供了多种I/O(Input/Output)通信模型,包括传统的阻塞I/O(BIO)、非阻塞I/O(NIO)以及异步I/O(AIO)。这些通信模型在不同的场景下有着各自的优势,理解和掌握它们对于优化...

    springboot 整合mina 源码,nio通讯基础教程,mina框架基础教程.rar

    在本教程中,我们将深入探讨如何整合Spring Boot与Mina框架,同时介绍Java NIO(非阻塞I/O)的基础知识。Spring Boot以其简洁、快速的起步方式深受开发者喜爱,而Mina则是一个强大的网络通信框架,常用于构建高性能...

    Java通讯模型-BIO、NIO、AIO综合演练

    本文将深入探讨Java中的三种主要通讯模型:BIO( Blocking I/O)、NIO(Non-blocking I/O)和AIO(Asynchronous I/O),并结合实际的代码示例进行综合演练。 **一、BIO(阻塞I/O)** 1. **概念**:BIO是Java早期的...

    netty jar(异步Nio通讯)

    netty 使用 4.0 jar 包 免费分享

    JAVA NIO 异步通信模板服务端

    **JAVA NIO 异步通信模板服务端** Java NIO(New Input/Output)是Java在J2SE 1.4版本中引入的一个新特性,它提供了与标准I/O完全不同的编程模型,尤其是在处理大量并发连接时,NIO展现出了更高的效率。本模板...

    Java NIO通信框架在电信领域的实践

    ### Java NIO通信框架在电信领域的实践 #### 华为电信软件技术架构演进 **1.1 电信软件概述** 电信软件是一个宽泛的概念,根据功能和应用场景的不同大致可以分为两大类:系统软件和业务应用软件。系统软件通常...

    NIO网络通讯编程

    NIO(Non-blocking I/O,非阻塞I/O)是Java平台中的一种I/O模型,与传统的BIO(Blocking I/O,阻塞I/O)相比,NIO在处理高并发、大数据传输时表现出更高的效率和更好的性能。NIO的核心概念包括通道(Channel)、缓冲...

    Ioserver java Nio socket 框架

    Ioserver java Nio socket 框架 是个不错的NIO 通讯框架,本来想学习mina框架,看了看mina的源码太头痛,本人觉得看懂了Ioserver 再看mina的框架,想多的学习 java NIO 的也可以下载 看看,很值得学习啊!!!

    seata源码研究.docx

    Nacos的通讯原理及Netty的NIO通讯 Nacos(命名与配置服务)作为一个服务发现与配置管理基础设施,其核心通讯机制依赖于Netty的NIO技术。Netty是一个高性能、异步事件驱动的网络应用框架,它使得开发健壮的服务端和...

    即时通讯-nio

    用java编写的nio通信的例子,nio是io编程的新版本,比io较流行。同时本例子是适用socket通信的。可以在此基础上,添加您的个人应用。本例子适用于:java通信的学习者,android平台通信的学习者。

    JavaNIO的通讯组件Gecko-Java.zip

    Gecko是一个Java NIO的通讯组件,它在一个轻量级的NIO框架的基础上提供了更高层次的封装和功能。支持的RPC调用方式包括RR(request-response)和pipeline 特性: 可插拔的协议设计 连接池 分组管理和负载均衡 ...

    3种下载文件程序的思考,为何使用NIO进行异步网络通讯

    标题中的“3种下载文件程序的思考,为何使用NIO进行异步网络通讯”提示了我们探讨的主题,即网络通信中的不同下载策略以及为何选择非阻塞I/O(Non-blocking I/O, NIO)作为异步通信的方式。在这个话题中,我们将深入...

    java nio im(server+client)

    在这个Java NIO IM(即时通讯)服务器和客户端的示例中,我们将探讨如何利用NIO进行双向通信,并理解其背后的机制。 1. **NIO基础概念** - **通道(Channel)**:在NIO中,数据是通过通道进行传输的。通道类似于流...

    tomcat7调优

    Tomcat7调优主要包括禁用不必要的AJP协议、切换到更高效的NIO通讯模式以及合理配置JVM参数。这些步骤有助于减少资源消耗,提高并发处理能力,从而提升整体系统性能。同时,持续监控和调整是保持Tomcat高效运行的关键...

    dubbo 分布式服务框架 开发者学习文档 PDF格式

    首先,Dubbo的核心组件之一是高性能的NIO通讯机制。NIO(Non-blocking I/O)允许在单个线程中处理多个连接,大大提高了服务器处理并发请求的能力。Dubbo通过实现NIO,提供了高效的网络通信能力,确保了服务间的快速...

    JAVANIO在Socket通讯中的应用

    ### JAVANIO在Socket通讯中的应用 #### 引言 在Java开发中,网络通信是常见需求之一,其中Socket编程是最基础也是最重要的技术之一。然而,在传统的Java Socket编程中,由于采用的是阻塞I/O模型,即所有的读写操作...

    NIO系列DATASHEET.pdf

    ### NIO系列DATASHEET.pdf知识点总结 #### 一、NIO系列产品概述 **NIO系列DATASHEET.pdf**提供了NIO系列产品的详细介绍和技术规格,该文档覆盖了多个型号的产品,包括不同类型的输入输出模块、电源设备以及网络...

Global site tag (gtag.js) - Google Analytics