Skip to content

Commit 573675d

Browse files
committed
nio
1 parent f1508ad commit 573675d

12 files changed

Lines changed: 840 additions & 0 deletions

File tree

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.example.nio.FileChannelText;
2+
3+
import java.io.File;
4+
import java.io.FileNotFoundException;
5+
import java.io.IOException;
6+
import java.io.RandomAccessFile;
7+
import java.nio.ByteBuffer;
8+
import java.nio.channels.FileChannel;
9+
10+
/**
11+
* Created by guolei on 16-8-6.
12+
* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
13+
* | 没有神兽,风骚依旧! |
14+
* | QQ:1120832563 |
15+
* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
16+
*/
17+
18+
19+
public class FileChannelDemo {
20+
21+
public static void main(String[] args){
22+
FileChannel fc = null;
23+
try {
24+
fc = new RandomAccessFile("./1.txt","rw").getChannel();
25+
ByteBuffer bf = ByteBuffer.allocate(1024);
26+
fc.read(bf);
27+
bf.flip();
28+
while (bf.hasRemaining()){
29+
System.err.println((char) bf.get());
30+
}
31+
fc.close();
32+
} catch (FileNotFoundException e) {
33+
e.printStackTrace();
34+
} catch (IOException e) {
35+
e.printStackTrace();
36+
} finally {
37+
if (fc.isOpen()){
38+
try {
39+
fc.close();
40+
} catch (IOException e) {
41+
e.printStackTrace();
42+
}
43+
}
44+
}
45+
}
46+
}

IO/code/nio/mapped/mapped.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.example.nio.mapped;
2+
3+
import java.io.IOException;
4+
import java.io.RandomAccessFile;
5+
import java.nio.MappedByteBuffer;
6+
import java.nio.channels.FileChannel;
7+
8+
/**
9+
* Created by guolei on 16-8-8.
10+
* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
11+
* | 没有神兽,风骚依旧! |
12+
* | QQ:1120832563 |
13+
* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
14+
*/
15+
16+
17+
public class mapped {
18+
19+
static int length = 0x8FFFFFF ;//128M
20+
public static void main(String[] args){
21+
try {
22+
MappedByteBuffer mappedByteBuffer = new RandomAccessFile("./1.txt","rw").getChannel().map(
23+
FileChannel.MapMode.READ_WRITE,0,length);
24+
for (int i = 0; i < length; i++) {
25+
mappedByteBuffer.put((byte)'x');
26+
}
27+
System.err.println("end");
28+
} catch (IOException e) {
29+
e.printStackTrace();
30+
}
31+
}
32+
}

IO/code/nio/nio.md

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
### Java Nio
2+
3+
[参考资料](http://ifeve.com/java-nio-channel-to-channel/)
4+
[参考资料](http://blog.csdn.net/u013256816/article/details/51457215)
5+
[参考资料](http://tutorials.jenkov.com/java-nio/selectors.html)
6+
7+
nio是非阻塞性的,面向缓冲区的。
8+
nio的目的是为了提高速度,尤其是在文件IO与网络IO中。
9+
10+
### nio中的几个核心概念
11+
通道和缓存器(相当于煤层和运煤车)
12+
13+
* Channels
14+
* Buffers
15+
* Selectors
16+
17+
channel,既可以将Buffer中的数据度渠道channel中,也可以将数据输出到buffer中。
18+
19+
Channel有下面几种类型。
20+
21+
* FileChannel 文件
22+
* DatagramChannel udp
23+
* SocketChannel 通过tcp读取网络中的数据
24+
* ServerSocketChannel 监听新进来的tcp链接,像web服务器那样
25+
26+
Buffer的类型
27+
28+
* ByteBuffer
29+
* CharBuffer
30+
* DoubleBuffer
31+
* FloatBuffer
32+
* IntBuffer
33+
* LongBuffer
34+
* ShortBuffer
35+
36+
Selector
37+
38+
Selector允许单线程处理多个Channel。得向Selector注册Channel,然后调用它的select方法。
39+
40+
_ _ _
41+
42+
### Channel
43+
44+
* 双向的,既可以写入数据,也可以读取数据
45+
* 可以进行异步读写
46+
* 总要先读到一个Buffer,或者总要从一个Buffer中写入
47+
48+
例子
49+
50+
```
51+
try {
52+
FileChannel fc = new RandomAccessFile("./1.txt","rw").getChannel();
53+
ByteBuffer bf = ByteBuffer.allocate(1024);
54+
//将输入读入buffer
55+
fc.read(bf);
56+
bf.flip();
57+
while (bf.hasRemaining()){
58+
System.err.println((char) bf.get());
59+
}
60+
} catch (FileNotFoundException e) {
61+
e.printStackTrace();
62+
} catch (IOException e) {
63+
e.printStackTrace();
64+
}
65+
```
66+
67+
* flip的作用是翻转,意思就是,如果当前为写入状态,如果我们要读取数据,就需要调用他来翻转一下。
68+
* hasRemaining是判断是否有下一个byte
69+
70+
如果我们当前为read,我们还想进行以下read操作,那么我们需要调用下clear或者compact清除已经读过的数据,没读过的数据将会
71+
被放置在头部方法为每个read做好准备。
72+
73+
我们可以通过transferTo 和 transferFrom方法来链接两个通道
74+
75+
_ _ _
76+
77+
Buffer
78+
79+
Buffer四个索引如下
80+
81+
* mark 标记
82+
* position 位置
83+
* limit 界限
84+
* capacity 容量
85+
86+
* limit和capacity位于末尾,position位于首位
87+
* 调用mark()方法将mark标记设置为position
88+
* 调用buffer的get方法将,mark标记往后移
89+
* put或者reset方法,将position设置为mark的值
90+
91+
写入数据
92+
93+
* read 或 put方法
94+
95+
从buffer中读数据到channel
96+
97+
* channel的write方法,buf的get方法。
98+
99+
rewind方法,将position设置为0
100+
101+
enquals
102+
103+
equals()
104+
105+
当满足下列条件时,表示两个Buffer相等:
106+
107+
有相同的类型(byte、char、int等)。
108+
Buffer中剩余的byte、char等的个数相等。
109+
Buffer中所有剩余的byte、char等都相同。
110+
111+
112+
compareTo()方法
113+
114+
compareTo()方法比较两个Buffer的剩余元素(byte、char等), 如果满足下列条件,则认为一个Buffer“小于”另一个Buffer:
115+
116+
第一个不相等的元素小于另一个Buffer中对应的元素 。
117+
所有元素都相等,但第一个Buffer比另一个先耗尽(第一个Buffer的元素个数比另一个少)。
118+
119+
* capacoty() 返回缓冲区容量
120+
* clear() 清空缓冲区,position设置0,limit设为容量
121+
* flip() limit设为position,position设置为0,
122+
* remaining() 返回limit-position
123+
* hasRemaining() 若有介于position和limit之间的
124+
125+
_ _ _
126+
127+
### Scatter/Gather
128+
129+
Scatter,从一个Channel中读取的数据分散到n个缓冲区
130+
Gather,将N个Buffer里的内容按照顺序发送到一个Channel里。
131+
132+
read(ByteBuffer[] dsts)
133+
write(ByteBuffer[] srcs)
134+
135+
### 通道之间的数据传输
136+
137+
transforFrom可以将数据从源通道传输到目标通道
138+
tramstiForm 一样,只不过就是调用顺序不一样。
139+
140+
### Selector
141+
142+
Selector(选择器)是Java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件。
143+
这样,一个单独的线程可以管理多个channel,从而管理多个网络连接。
144+
145+
单个线程管理多个通道
146+
147+
Selector的创建。 open方法。
148+
向Selector注册通道
149+
150+
channel.configureBlocking(false);
151+
SelectionKey key = channel.register(selector,
152+
Selectionkey.OP_READ);
153+
154+
注意register()方法的第二个参数。这是一个“interest集合”,意思是在通过Selector监听Channel时对什么事件感兴趣。可以用|,多个
155+
可以监听四种不同类型的事件:
156+
157+
* Connect
158+
* Accept
159+
* Read
160+
* Write
161+
162+
Selector注册Channel时,register()方法会返回一个SelectionKey对象。这个对象包含了一些你感兴趣的属性:
163+
164+
interest集合
165+
ready集合
166+
Channel
167+
Selector
168+
附加的对象(可选)
169+
170+
interest集合是你所选择的感兴趣的事件集合.
171+
interest集合,像这样:
172+
nt interestSet = selectionKey.interestOps();
173+
boolean isInterestedInAccept = (interestSet & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT;
174+
boolean isInterestedInConnect = interestSet & SelectionKey.OP_CONNECT;
175+
boolean isInterestedInRead = interestSet & SelectionKey.OP_READ;
176+
boolean isInterestedInWrite = interestSet & SelectionKey.OP_WRITE;
177+
178+
可以看到,用“位与”操作interest 集合和给定的SelectionKey常量,可以确定某个确定的事件是否在interest 集合中。
179+
180+
ready集合
181+
ready 集合是通道已经准备就绪的操作的集合。
182+
Channel + Selector
183+
Channel channel = selectionKey.channel();
184+
Selector selector = selectionKey.selector();
185+
186+
附加的对象
187+
188+
可以将一个对象或者更多信息附着到SelectionKey上,这样就能方便的识别某个给定的通道。例如,可以附加 与通道一起使用的Buffer,或是包含聚集数据的某个对象。使用方法如下:
189+
查看源代码
190+
打印
191+
帮助
192+
electionKey.attach(theObject);
193+
Object attachedObj = selectionKey.attachment();
194+
195+
还可以在用register()方法向Selector注册Channel的时候附加对象。如:
196+
SelectionKey key = channel.register(selector, SelectionKey.OP_READ, theObject);
197+
198+
通过Selector选择通道
199+
select()阻塞到至少有一个通道在你注册的事件上就绪了。
200+
201+
select(long timeout)和select()一样,除了最长会阻塞timeout毫秒(参数)。
202+
203+
selectNow()不会阻塞,不管什么通道就绪都立刻返回
204+
(译者注:此方法执行非阻塞的选择操作。如果自从前一次选择操作后,没有通道变成可选择的,则此方法直接返回零。)。
205+
206+
SelectKeys,调用了select方法之后,返回已选择键集中的就绪通道。
207+
208+
wakeUp() 某个线程调用select()方法后阻塞了,即使没有通道已经就绪,也有办法让其从select()方法返回。
209+
只要让其它线程在第一个线程调用select()方法的那个对象上调用Selector.wakeup()方法即可。阻塞在select()方法上的线程会立马返回。
210+
211+
close 关闭Selector,通道本身不会关闭
212+
213+
完整的实例。
214+
215+
_ _ _
216+
217+
### FileChannel
218+
file.getChannel() 获取channel
219+
220+
分配一个Buffer,ByteBuffer bb = ByteBuffer.allocate(size).
221+
222+
将数据从channel中读到buffer channel.read(byte)
223+
224+
写入数据 channel.write
225+
226+
### SocketChannel
227+
228+
[参考资料](http://ifeve.com/socket-channel/)
229+
230+
### SocketChannelServer
231+
232+
### DatagramChannel
233+
234+
[实现UDP协议传输](http://blog.csdn.net/foart/article/details/47608475)
235+
236+
* 不需要connet建立链接
237+
* 通过send发送数据
238+
* 通过receive接受数据
239+
240+
### Java IO 和 NIO
241+
242+
IO NIO
243+
面向流 面向缓冲
244+
阻塞IO 非阻塞IO
245+
无 选择器
246+
247+
248+
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.example.nio.niosocket;
2+
3+
import java.io.IOException;
4+
import java.net.InetSocketAddress;
5+
import java.net.Socket;
6+
import java.nio.ByteBuffer;
7+
import java.nio.channels.SocketChannel;
8+
9+
/**
10+
* Created by guolei on 16-8-6.
11+
* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
12+
* | 没有神兽,风骚依旧! |
13+
* | QQ:1120832563 |
14+
* ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
15+
*/
16+
17+
18+
public class SocketChannelClient {
19+
20+
public static void main(String[] args){
21+
SocketChannel socketChannel;
22+
try {
23+
socketChannel = SocketChannel.open();
24+
socketChannel.connect(new InetSocketAddress("192.168.0.114",3334));
25+
socketChannel.configureBlocking(false);
26+
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
27+
byteBuffer.put(new String("hello,我来自客户端").trim().getBytes("utf-8"));
28+
byteBuffer.flip();
29+
socketChannel.write(byteBuffer);
30+
byteBuffer.clear();
31+
new Thread(new ReadFromServer(socketChannel)).start();
32+
} catch (IOException e) {
33+
e.printStackTrace();
34+
}
35+
}
36+
37+
static class ReadFromServer implements Runnable{
38+
private SocketChannel socketChannel;
39+
40+
public ReadFromServer(SocketChannel socketChannel){
41+
this.socketChannel = socketChannel;
42+
}
43+
44+
@Override
45+
public void run() {
46+
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
47+
while (true){
48+
try {
49+
while (socketChannel.read(byteBuffer) != -1){
50+
if (byteBuffer.get(0) != 0){
51+
System.err.println(new String(byteBuffer.array()).trim());
52+
return;
53+
}
54+
}
55+
} catch (IOException e) {
56+
e.printStackTrace();
57+
}
58+
}
59+
60+
}
61+
}
62+
}

0 commit comments

Comments
 (0)