- 浏览: 1237644 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (193)
- ant/maven (6)
- algorithm (5)
- tomcat/weblogic/jboss (6)
- javascript/jquery (13)
- java (33)
- flex/flash (0)
- JPA/Hibernate/myBatis (18)
- java concurrent (7)
- test (2)
- windows/linux (6)
- java collection (7)
- design pattern (2)
- life/health (3)
- database (12)
- IDE (4)
- spring/ejb (20)
- html/css/ckeditor (7)
- jsp/servlet (3)
- java io (13)
- java security (4)
- jni (0)
- svn/git (2)
- english (2)
- java jmx (1)
- xml (1)
- struts/springmvc (9)
- middleware (2)
- cache (1)
- cglib (3)
最新评论
-
jlotusYo:
博主,真感谢。
Java 密码扩展无限制权限策略文件 -
senninha:
这个。。是api说明吧。。
ScheduledExecutorService 源码分析 -
zoutao2008:
请问大文件如何处理?按你这种方式的话,文件超过200M时就会报 ...
hessian系列之二:上传文件 -
lwj1113:
lwj1113 写道谢谢博主这么细致的demo;在系列五中通过 ...
myBatis系列之五:与Spring3集成 -
lwj1113:
谢谢博主这么细致的demo;在系列五中通过testng测试类跑 ...
myBatis系列之五:与Spring3集成
Java NIO (Nonblocking IO)解决了常规IO的瓶颈:
a. 服务端的监听操作会阻塞而无法处理其它事务。多线程方式受到线程池和系统资源的限制,同步操作将会变得复杂。多线程操作磁盘将会导致响应慢甚至死锁。
b. 普通I/O通过Stream来操作,开发简单,但是对I/O的控制力弱
c. 普通IO的读取或写入会在JVM内存和操作系统内存之间进行复制,开销较大。
普通客户端和服务端的Socket通信:
Socket 编程 - 单个客户端
下面通过ServerSocketChannel和SocketChannel来实现客户端和服务端的NIO通信:
1. 服务端
2. 客户端
a. 服务端的监听操作会阻塞而无法处理其它事务。多线程方式受到线程池和系统资源的限制,同步操作将会变得复杂。多线程操作磁盘将会导致响应慢甚至死锁。
b. 普通I/O通过Stream来操作,开发简单,但是对I/O的控制力弱
c. 普通IO的读取或写入会在JVM内存和操作系统内存之间进行复制,开销较大。
普通客户端和服务端的Socket通信:
Socket 编程 - 单个客户端
下面通过ServerSocketChannel和SocketChannel来实现客户端和服务端的NIO通信:
1. 服务端
public class TCPEchoServerNIO { private static final int BUFSIZE = 256; private static final long TIMEOUT = 3000; public static void main(String[] args) throws IOException { args = new String[1]; args[0] = "4451"; Selector selector = Selector.open(); // 工厂模式创建选择器 ServerSocketChannel servChan = ServerSocketChannel.open(); // 工厂模式创建服务套接字通道 servChan.socket().bind(new InetSocketAddress(Integer.parseInt(args[0]))); // 绑定到指定端口 servChan.configureBlocking(false); // 非阻塞模式(必须) servChan.register(selector, SelectionKey.OP_ACCEPT); // 通道注册到选择器中。是通道的方法,不是选择器的。 while (true) { if (selector.select(TIMEOUT) == 0) { // 获取可进行I/O操作的通道的SelectionKey集 System.out.println("No channel needs I/O operations"); continue; } Iterator<SelectionKey> iter = selector.selectedKeys().iterator(); while (iter.hasNext()) { SelectionKey key = iter.next(); if (key.isAcceptable()) { // key关联的通道已准备好接收套接字连接(当客户端connect服务端时) handleAccept(key); } if (key.isReadable()) { // key关联的通道已准备好读取(客户端发送的数据已到达) handleRead(key); } if (key.isValid() && key.isWritable()) { // key有效(自key创建后,至调用cancel()、或通道关闭,或selector关闭之前),且通道已准备好写(客户端读取服务端返回) handleWrite(key); } iter.remove(); // 每次select()都会append新的SelectionKey,所以移除已处理的,防止下次重复处理 } } } private static void handleAccept(SelectionKey key) throws IOException, ClosedChannelException { SocketChannel clntChan = ((ServerSocketChannel) key.channel()).accept(); if (clntChan != null) { clntChan.configureBlocking(false); // 通道必须为非阻塞模式 clntChan.register(key.selector(), SelectionKey.OP_READ, ByteBuffer.allocate(BUFSIZE)); // 注册通道的读取事件(当客户端发送数据到服务端时发生),并创建一个缓冲区存放传输数据 } } private static void handleRead(SelectionKey key) throws IOException { SocketChannel clntChan = (SocketChannel) key.channel(); ByteBuffer buf = (ByteBuffer) key.attachment(); // 获取key关联的附件,也就是前面创建的缓冲区 int bytesRead = clntChan.read(buf); // 将客户端发过来的数据放到缓冲区 if (bytesRead == -1) { // 从客户端读取到的数据为空(当客户端关闭通道时,会触发该读取事件),说明已关闭 clntChan.close(); } else if (bytesRead > 0) { key.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE); // 接收 客户端发送数据事件 | 客户端读取服务端返回事件 } } private static void handleWrite(SelectionKey key) throws IOException { ByteBuffer buf = (ByteBuffer) key.attachment(); buf.flip(); // 从先前写入的起始位置读取 SocketChannel clntChan = (SocketChannel) key.channel(); clntChan.write(buf); // 将客户端发送的数据写回客户端,完成“回显”功能 if (!buf.hasRemaining()) { // 缓冲区没有数据 key.interestOps(SelectionKey.OP_READ); // 不需要再往通道写,只对读事件(客户端又发送数据到服务端)感兴趣 } buf.compact(); // 缓冲区剩余的数据,移动到缓冲区的起始部位,给下次存放数据腾出空间 } }
2. 客户端
public class TCPEchoClientNIO { public static void main(String[] args) throws IOException { args = new String[3]; args[0] = "localhost"; args[1] = "Hello NIO"; args[2] = "4451"; String server = args[0]; byte[] words = args[1].getBytes(); // 待发送字符串的字节数组形式 int servPort = args.length == 3 ? Integer.parseInt(args[2]) : 4451; // 静态工厂方法创建通道,设置为非阻塞模式 SocketChannel clntChan = SocketChannel.open(); clntChan.configureBlocking(false); // 初始化连接,并等待连接过程结束 // 调用非阻塞通道的方法总是立即返回而不管是否完成,所以要采用轮询方式获取状态 if (!clntChan.connect(new InetSocketAddress(server, servPort))) { // 触发服务端通道的OP_ACCEPT while (!clntChan.finishConnect()) { System.out.println("Wait for connecting finished"); } } ByteBuffer writeBuf = ByteBuffer.wrap(words); // 发送缓冲区 ByteBuffer readBuf = ByteBuffer.allocate(words.length); // 接收缓冲区,长度和发送数据相同(回显) int totalBytesRcvd = 0; int bytesRcvd; while (totalBytesRcvd < words.length) { if (writeBuf.hasRemaining()) { // 发送缓冲区还有数据 clntChan.write(writeBuf); // 向服务器发送数据,触发通道的OP_READ } bytesRcvd = clntChan.read(readBuf); // 获取服务端返回的数据,触发通道的OP_WRITE totalBytesRcvd += bytesRcvd; System.out.println("Receiving " + bytesRcvd + " bytes"); } System.out.println("Received: " + new String(readBuf.array(), 0, totalBytesRcvd)); // 转化为字符串 clntChan.close(); // 关闭通道,触发通道的OP_READ,数据为空 } }
发表评论
-
Netty系列之二、Netty组件
2014-10-12 19:55 0Netty主要由以下几个组件构成: Bootstrap o ... -
Netty系列之二:传输方式
2014-09-17 22:35 0NIO (Non-blocking I/O) io.netty ... -
Java正则表达式实例
2014-08-25 22:50 1890题目: 有两个文件context.txt和words ... -
quartz系列之九:存储
2014-08-05 13:16 0这里以1.8.x为例: 任务 ... -
JVM 四种引用
2014-04-24 19:56 17221. 强引用 指通过普通 ... -
Proxy 源码分析
2014-04-21 10:47 0public class Proxy implements ... -
NIO UDP 编程
2014-04-17 23:18 4206和TCP的SocketChannel类似,UDP的Dat ... -
Matcher 源码分析
2014-04-15 14:45 0首先看下接口: public interface Matc ... -
BTrace 使用
2014-03-20 18:03 0简介 Btrace (Byte Trace)是Sun推出的一款 ... -
hessian系列之二:上传文件
2014-02-17 17:16 6155hessian较早版本通过 byte[] 进行文件传输;4.0 ... -
hessian系列之三:与Spring集成
2014-02-17 20:21 17814Spring封装了hessian客户端和服务端的通用代码,把实 ... -
hessian系列之一:Hello world
2014-01-06 20:51 2257Hessian是一个Web Service的轻量级二进制协议, ... -
XStream:自定义转换器
2013-12-30 22:47 0XStream是一款不错的oxm (Object-XML ma ... -
Http连接工具类
2013-12-28 16:13 0public class HttpConnUtil { ... -
Integer源码分析
2013-12-26 19:59 0private static String toU ... -
全排序
2013-12-23 21:02 0写一个函数, 如 foo(String str), 打印出 s ... -
logback系列之四:输出日志到不同文件
2013-12-03 16:25 68757logback系列之一:输出日志到控制台 logback系列之 ... -
Properties 源码分析
2013-11-26 10:32 01. Properties类扩展了Hashtable,用来保存 ... -
logback系列之三:输出日志到文件(滚动)
2013-11-16 23:37 64276logback系列之一:输出日志到控制台 logback系列之 ... -
logback系列之二:输出日志到文件
2013-11-15 15:20 30240logback系列之一:输出日志到控制台 logback系列之 ...
相关推荐
使用NIO channel 实现的加法服务器 附带客户端 服务器端代码 简单易懂
socket编程 java代码示例,客户端发送消息,服务端接收
非常详细地讲解了NIO中的缓冲区、通道、选择器、编码,以及使用Socket技术实现TCP/IP和UDP编程,细化到了演示全部SocketOption的特性,这对理解基于NIO和Socket技术为基础所开发的NIO框架是非常有好处的,本书以案例...
《NIO与Socket编程技术指南》_高洪岩
网络通信工具,服务端和客户端连接测试工具,可单条发送,循环发送,模拟多客户端发送,本工具可以作为网络通信工具或压力测试工具, Java NIO Socket编程,需JAVA运行环境
基于NIO的socket举例 基于NIO的socket举例 基于NIO的socket举例 基于NIO的socket举例 基于NIO的socket举例基于NIO的socket举例 基于NIO的socket举例
本资料提供的是用Socket编程实现聊天程序。 有两种:流式Socket(SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。流式是一种面向连接的Socket,针对于面向连接的TCP服务应用;数据报式Socket是一种无连接的Socket,...
NULL 博文链接:https://j2ee2009.iteye.com/blog/695697
Socket编程指南及示例程序.doc Socket编程指南及示例程序.doc
《NIO与Socket编程技术指南》_高洪岩
基于java nio的服务器与客户端的开发指南
Java,NIO,教程 非堵塞IO编程
java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java...
网络socket编程指南,很好的东西,希望大家都努力学习,加油!!!
NIO编程技术指南_预览版
java bio nio aio socket
NULL 博文链接:https://zfms.iteye.com/blog/1535594
用于博文https://blog.csdn.net/lyz_zyx/article/details/104062815《Android网络编程(十四) 之 Socket与NIO》中演示Socket与NIO使用的Demo
大并发服务器编程模型 windows iocp完成端口模型可支持1万大并发,但是linux能作到5万大并发
socket的tcp/udp(多播) nio的tcp/udp mina 均有服务端/客服端