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 ...
随机推荐
- curl使用例子
地址:http://phpbook.phpxy.com/34771 参考:http://php.net/manual/zh/function.curl-setopt.php 我们将curl的步骤分为以 ...
- 《linux系统及其编程》实验课记录(一)
实验 1:登录和使用基本的 Linux 命令 实验环境: 安装了 Red Hat Enterprise Linux 6.0 可运行系统,并且是成功验证系统. 有另外一个无特权用户 student,密码 ...
- Asp.net控制Tomcat启动关闭的实现方法
一.场景 近日有个项目客户要求能自己配置相关权限.由于历史原因这个项目采用的是公司以前的权限系统.这个权限系统很强大,不过有个弊端,就是每增加一个权限菜单都要重启才能生效,不然就要等1天它缓存过期后才 ...
- Java反射基础(二)
获取域 1. 通过反射API可以获取到类中公开的静态域和对象中的实例域.得到表示域的java.lang.reflect.Field类的对象之后,就可以获取和设置域的值. 与获取构造方法类似,Cla ...
- java关键字及含义
http://blog.csdn.net/hfmbook/article/details/7634385
- cxGrid 循环选择条目
Delphi DevExpress CxGrid 循环选择条目 整理出来的,直接复制粘贴即可使用 以下是从网络上复制粘帖到的,实践证明,利用以下代码进行获取选择行是错误的. 当我们利用 CxGrid进 ...
- cxGrid 使用指南 1
1:cxgrid是应该数据关联的控件,类似dbgrid.2:一般用来查阅表信息,如果要修改的话,直接在上面编辑或添加 非常不方便通常要放几个EDit来对选中的记录进行编辑或添加记录. 因为表一般都有主 ...
- servlet ; basepath ; sendredirected ;
Eclipse 新建 jsp页面里自动生成以下代码: <%String path = request.getContextPath();String basePath = request.get ...
- 【BZOJ4709】[Jsoi2011]柠檬 斜率优化+单调栈
[BZOJ4709][Jsoi2011]柠檬 Description Flute 很喜欢柠檬.它准备了一串用树枝串起来的贝壳,打算用一种魔法把贝壳变成柠檬.贝壳一共有 N (1 ≤ N ≤ 100,0 ...
- HDU 3388 Coprime(容斥原理+二分)
Coprime Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Su ...