NIO复习03
SocketChannel:
1. Java NIO中的SocketChannel是一个连接到TCP网络套接字的通道。可以通过以下2种方式创建SocketChannel:
打开一个SocketChannel并连接到互联网上的某台服务器。
一个新连接到达ServerSocketChannel时,会创建一个SocketChannel。
2. 打开 SocketChannel(发送端channel?):
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("http://jenkov.com", 80));
3. 关闭 SocketChannel:当用完SocketChannel之后调用SocketChannel.close()关闭SocketChannel:socketChannel.close();
4. 从 SocketChannel 读取数据:要从SocketChannel(接收端channel?)中读取数据,调用一个read()的方法之一。
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = socketChannel.read(buf);
首先,分配一个Buffer。从SocketChannel读取到的数据将会放到这个Buffer中。然后,调用SocketChannel.read()。该方法将数据从SocketChannel 读到Buffer中。read()
方法返回的int值表示读了多少字节进Buffer里。如果返回的是-1,表示已经读到了流的末尾(连接关闭了)
5. 写入 SocketChannel : 写数据到SocketChannel(发送端channel?)用的是SocketChannel.write()方法,该方法以一个Buffer作为参数。示例如下:
String newData = "New String to write to file..." + System.currentTimeMillis();
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();
while(buf.hasRemaining()) {
channel.write(buf);
}
注意SocketChannel.write()方法的调用是在一个while循环中的。Write()方法无法保证能写多少字节到SocketChannel。所以,我们重复调用write()直到Buffer没有要写的字节为止。
6. 非阻塞模式
可以设置 SocketChannel 为非阻塞模式(non-blocking mode).设置之后,就可以在异步模式下调用connect(), read() 和write()了。
connect():如果SocketChannel在非阻塞模式下,此时调用connect(),该方法可能在连接建立之前就返回了。为了确定连接是否建立,可以调用finishConnect()的方法。像这样:
socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress("http://jenkov.com", 80));
while(! socketChannel.finishConnect() ){
//wait, or do something else...
}
write():非阻塞模式下,write()方法在尚未写出任何内容时可能就返回了。所以需要在循环中调用write()。前面已经有例子了,这里就不赘述了。
read():非阻塞模式下,read()方法在尚未读取到任何数据时可能就返回了。所以需要关注它的int返回值,它会告诉你读取了多少字节。
非阻塞模式与选择器: 非阻塞模式与选择器搭配会工作的更好,通过将一或多个SocketChannel注册到Selector,可以询问选择器哪个通道已经准备好了读取,写入等。
ServerSocketChannel
1. Java NIO中的 ServerSocketChannel 是一个可以监听新进来的TCP连接的通道, 就像标准IO中的ServerSocket一样。ServerSocketChannel类在 java.nio.channels包中。
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(9999));
while(true){
SocketChannel socketChannel = serverSocketChannel.accept();
//do something with socketChannel...
}
2. 打开 ServerSocketChannel:过调用 ServerSocketChannel.open() 方法来打开ServerSocketChannel.如:ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
3. 关闭 ServerSocketChannel:通过调用ServerSocketChannel.close() 方法来关闭ServerSocketChannel. 如:serverSocketChannel.close();
4. 监听新进来的连接:通过 ServerSocketChannel.accept() 方法监听新进来的连接。当 accept()方法返回的时候,它返回一个包含新进来的连接的 SocketChannel。因此, accept()方法
会一直阻塞到有新连接到达。通常不会仅仅只监听一个连接,在while循环中调用 accept()方法. 如下面的例子:
while(true){
SocketChannel socketChannel = serverSocketChannel.accept();
//do something with socketChannel...
}
当然,也可以在while循环中使用除了true以外的其它退出准则。
5. 非阻塞模式
ServerSocketChannel可以设置成非阻塞模式。在非阻塞模式下,accept() 方法会立刻返回,如果还没有新进来的连接,返回的将是null。 因此,需要检查返回的SocketChannel是否是null.如:
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(9999));
serverSocketChannel.configureBlocking(false);
while(true){
SocketChannel socketChannel = serverSocketChannel.accept();
if(socketChannel != null){
//do something with socketChannel...
}
}
Java NIO DatagramChannel:
1. Java NIO中的DatagramChannel是一个能收发UDP包的通道。因为UDP是无连接的网络协议,所以不能像其它通道那样读取和写入。它发送和接收的是数据包。
2. 打开 DatagramChannel:下面是 DatagramChannel 的打开方式:
DatagramChannel channel = DatagramChannel.open();
channel.socket().bind(new InetSocketAddress(9999));
这个例子打开的 DatagramChannel可以在UDP端口9999上接收数据包。
3. 接收数据:通过receive()方法从DatagramChannel接收数据,如:
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
channel.receive(buf);
receive()方法会将接收到的数据包内容复制到指定的Buffer. 如果Buffer容不下收到的数据,多出的数据将被丢弃。
4. 发送数据
通过send()方法从DatagramChannel发送数据,如:
String newData = "New String to write to file..." + System.currentTimeMillis();
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());
buf.flip();
int bytesSent = channel.send(buf, new InetSocketAddress("jenkov.com", 80));
这个例子发送一串字符到”jenkov.com”服务器的UDP端口80。 因为服务端并没有监控这个端口,所以什么也不会发生。也不会通知你发出的数据包是否已收到,因为UDP在数据传送方面没有任何保证。
5. 连接到特定的地址
可以将DatagramChannel“连接”到网络中的特定地址的。由于UDP是无连接的,连接到特定地址并不会像TCP通道那样创建一个真正的连接。而是锁住DatagramChannel ,让其只能从
特定地址收发数据。这里有个例子:
channel.connect(new InetSocketAddress("jenkov.com", 80));
当连接后,也可以使用read()和write()方法,就像在用传统的通道一样。只是在数据传送方面没有任何保证。这里有几个例子:
int bytesRead = channel.read(buf);
int bytesWritten = channel.write(but);
Pipe
1. Java NIO 管道是2个线程之间的单向数据连接。Pipe有一个source通道和一个sink通道。数据会被写到sink通道,从source通道读取。
2. 创建管道:通过Pipe.open()方法打开管道。例如:
Pipe pipe = Pipe.open();
3. 向管道写数据:要向管道写数据,需要访问sink通道。像这样:
Pipe.SinkChannel sinkChannel = pipe.sink();
通过调用SinkChannel的write()方法,将数据写入SinkChannel,像这样:
String newData = "New String to write to file..." + System.currentTimeMillis();
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
sbuf.put(newData.getBytes());
buf.flip();
while(buf.hasRemaining()) {
sinkChannel.write(buf);
}
4. 从管道读取数据:从读取管道的数据,需要访问source通道,像这样:
Pipe.SourceChannel sourceChannel = pipe.source();
调用source通道的read()方法来读取数据,像这样:
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = sourceChannel.read(buf);
read()方法返回的int值会告诉我们多少字节被读进了缓冲区。
NIO复习03的更多相关文章
- Linux NIO 系列(03) 非阻塞式 IO
目录 一.非阻塞式 IO 附:非阻塞式 IO 编程 Linux NIO 系列(03) 非阻塞式 IO Netty 系列目录(https://www.cnblogs.com/binarylei/p/10 ...
- JAVA NIO复习笔记
1. JAVA NIO是什么? 从JDK1.4开始,java提供了一系列改进的输入/输出处理的新功能,这些功能被统称为新IO(New IO,简称NIO),新增了许多用于处理输入/输出的类,这些类都被放 ...
- NIO复习02
Selector 1. Selector(选择器)是Java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件.这样,一个单独的线程可以管理多个channel,从而管 ...
- NIO复习01
NIO 概述: 1. Java NIO 由以下几个核心部分组成:Channels Buffers Selectors 2. 主要Channel的实现:FileChann ...
- nodejs复习03
文件系统fs 重命名 fs.rename() fs.renameSync 优先选择异步,可以进行异常判断 打开关闭文件 fd = fs.openSync(file, flags) fs.closeSy ...
- C#基础总复习03
继续更新...接下来就是面向对象的知识了 1.面向对象:概念:使用面向对象的思想进行编程可以让的程序变得扩展性更高,便于维护: 我们在现实生活中去描述一个人的时候,通过描述这个人的特征和行为. 我们在 ...
- nio复习总结
观察者: 多个对象依赖一个对象的状态, 当这个对象状态发生改变时,依次通知多个对象. 消息的分发和处理 事件驱动 / IO多路复用 借助select epoll等 reactor: io事件触发时, ...
- 编译原理--02 自顶向下、自底向上的LR分析复习(清华大学出版社第3版)
前言 目录 01 文法和语言.词法分析复习 02 自顶向下.自底向上的LR分析复习 03 语法制导翻译和中间代码生成复习 04 符号表.运行时存储组织和代码优化复习 第4章 自顶向下的语法分析方法 确 ...
- 《2013传智播客视频》-wmv,avi,mp4.目录
\!--14俄罗斯方块\视频\.复习.avi; \!--14俄罗斯方块\视频\ 复习.avi; \!--14俄罗斯方块\视频\ 形状旋转.avi; \!--14俄罗斯方块\视频\ 判断形状能否变形.a ...
随机推荐
- ar0331
aptina公司出品 分三个文档:ar0331_ds.pdf 数据表ar0331_dg.pdf 开发指导ar0331_rr_d.pdf 相关寄存器 色调映射(Tone Mapping):http:// ...
- Hadoop大数据处理读书笔记
几个关键性的概念 云计算:是指利用大量计算节点构成的可动态调整的虚拟化计算资源.通过并行化和分布式计算技术,实现业务质量可控的大数据处理的计算技术. NameNode:是HDFS系统中的管理者.它负责 ...
- AngularJS 讲解,三 过滤器
过滤器用来格式化需要展示给用户的数据.AngularJS有很多实用的内置过滤器,同时也提供了方便的途径可以自己创建过滤器. 在HTML中的模板绑定符号{{ }}内通过|符号来调用过滤器.例如:{{va ...
- jpa单向一对多关联映射
如果在一的@OneToMany有@manyToOne则是双向一对多关联,如果在多的那面没有@manyToOne关联则是单向一对多关联 class和student是一对多的关系 表结构 student ...
- 微信小程序直播
微信小程序直播(转) 通过PC实现推流,然后用小程序进行直播播放,也就是PC->小程序. 小程序支持 小程序的直播能力只针对某些类目开放并且需要申请开通. 支持的类目 社交 直播 教育 在线教育 ...
- 穿透Session 0 隔离(一)
服务(Service)对于大家来说一定不会陌生,它是Windows 操作系统重要的组成部分.我们可以把服务想像成一种特殊的应用程序,它随系统的“开启-关闭”而“开始-停止”其工作内容,在这期间无需任何 ...
- Class.forName()用法
主要功能 Class.forName(xxx.xx.xx)返回的是一个类. Class.forName(xxx.xx.xx)的作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的静态代码段. ...
- delphi,增删改查问题记录
新增时获取新的主键方法 1.oracle :sys_guid() 写法: 2.sql:pGetGUID 写法: {**************************************** ...
- Spoken English Practice( Believe it or not, I don't need to make believe its a big deal. (believe,deal, You don't say))
音标复习 绿色:连读:红色:略读:蓝色:浊化:橙色:弱读 口语蜕变(2017/6/25) Sorry, t ...
- 【Python之路】第二十一篇--Memcached、Redis
Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度 ...