Skip to content

Commit c67450a

Browse files
committed
Add Stage 8 Lesson 4
1 parent f0c5991 commit c67450a

File tree

10 files changed

+312
-0
lines changed

10 files changed

+312
-0
lines changed

「一入 Java 深似海 」/代码/segmentfault/deep-in-java/stage-8/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<module>stage-8-lesson-1</module>
1717
<module>stage-8-lesson-2</module>
1818
<module>stage-8-lesson-3</module>
19+
<module>stage-8-lesson-4</module>
1920
</modules>
2021

2122
</project>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<parent>
6+
<artifactId>stage-8</artifactId>
7+
<groupId>com.segmentfault</groupId>
8+
<version>1.0-SNAPSHOT</version>
9+
</parent>
10+
<modelVersion>4.0.0</modelVersion>
11+
12+
<artifactId>stage-8-lesson-4</artifactId>
13+
<name>「一入 Java 深似海 」系列 :: 第八期 :: 第四节</name>
14+
15+
16+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.segmentfault.deep.in.java.nio;
2+
3+
import java.nio.Buffer;
4+
import java.nio.ByteBuffer;
5+
6+
public class BufferDemo {
7+
8+
public static void main(String[] args) {
9+
10+
ByteBuffer buffer = ByteBuffer.allocate(8);
11+
// mark(-1),position(0),limit(8),capacity(8)
12+
buffer.put((byte) 1); // // mark(-1),position(1),limit(8),capacity(8)
13+
displayBufferMetadata(buffer);
14+
// [1,X,X,X,X,X,X,X]
15+
// p
16+
// position 倒回 0
17+
buffer.rewind(); // 倒带
18+
// [1,X,X,X,X,X,X,X]
19+
// p
20+
System.out.println(buffer.get());
21+
22+
// 当内容小于 8 字节
23+
//
24+
}
25+
26+
public static void displayBufferMetadata(Buffer buffer) {
27+
System.out.printf("当前 Buffer[ type : %s ] position = %d , limit = %d , capacity = %d%n",
28+
buffer.getClass().getName(),
29+
buffer.position(),
30+
buffer.limit(),
31+
buffer.capacity()
32+
);
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.segmentfault.deep.in.java.nio;
2+
3+
import java.io.IOException;
4+
import java.net.InetSocketAddress;
5+
import java.nio.Buffer;
6+
import java.nio.ByteBuffer;
7+
import java.nio.channels.ServerSocketChannel;
8+
import java.nio.channels.SocketChannel;
9+
10+
public class ChannelClientDemo {
11+
// select 和 epoll
12+
public static void main(String[] args) throws IOException, InterruptedException {
13+
// 客户端 SocketChannel
14+
try (SocketChannel socketChannel = SocketChannel.open();) {
15+
// 设置为非阻塞
16+
socketChannel.configureBlocking(false);
17+
// 连接服务端
18+
socketChannel.connect(new InetSocketAddress(8080));
19+
while (!socketChannel.finishConnect()) {
20+
System.out.println("等待连接到达...");
21+
}
22+
ByteBuffer buffer = ByteBuffer.allocate(8);
23+
while (socketChannel.read(buffer) != -1) {
24+
buffer.flip();
25+
while (buffer.hasRemaining()) {
26+
System.out.print((char)buffer.get());
27+
}
28+
buffer.clear();
29+
}
30+
}
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.segmentfault.deep.in.java.nio;
2+
3+
import java.io.IOException;
4+
import java.io.InputStream;
5+
import java.io.OutputStream;
6+
import java.nio.ByteBuffer;
7+
import java.nio.channels.Channels;
8+
import java.nio.channels.ReadableByteChannel;
9+
import java.nio.channels.WritableByteChannel;
10+
11+
public class ChannelRedirect {
12+
13+
public static void main(String[] args) throws IOException {
14+
// System.in
15+
// System.out
16+
// 传统 InputStream 和 OutputStream
17+
// copy(System.in, System.out);
18+
19+
//
20+
ReadableByteChannel readableByteChannel = Channels.newChannel(System.in);
21+
WritableByteChannel writableByteChannel = Channels.newChannel(System.out);
22+
copy(readableByteChannel, writableByteChannel);
23+
}
24+
25+
private static void copy(ReadableByteChannel readableByteChannel, WritableByteChannel writableByteChannel) throws IOException {
26+
ByteBuffer buffer = ByteBuffer.allocate(4 * 1024); // 4 K字节数组(堆内存)
27+
while (readableByteChannel.read(buffer) != -1) {
28+
buffer.flip(); // 记录当前 buffer limit = position (已读数据长度)
29+
// 优化写入
30+
if (buffer.hasRemaining()) {
31+
writableByteChannel.write(buffer);
32+
}
33+
buffer.clear();
34+
}
35+
36+
}
37+
38+
private static void copy(InputStream inputStream, OutputStream outputStream) throws IOException {
39+
byte[] buffer = new byte[4 * 1024]; // 4 K字节数组(堆内存)
40+
int readLength = -1;
41+
while ((readLength = inputStream.read(buffer)) != -1) {
42+
outputStream.write(buffer, 0, readLength);
43+
}
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.segmentfault.deep.in.java.nio;
2+
3+
import java.io.IOException;
4+
import java.net.InetSocketAddress;
5+
import java.nio.Buffer;
6+
import java.nio.ByteBuffer;
7+
import java.nio.channels.ServerSocketChannel;
8+
import java.nio.channels.SocketChannel;
9+
10+
public class ChannelServerDemo {
11+
// select 和 epoll
12+
public static void main(String[] args) throws IOException, InterruptedException {
13+
// 服务端 SocketChannel
14+
try (ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();) {
15+
// 绑定服务端
16+
serverSocketChannel.socket().bind(new InetSocketAddress(8080));
17+
// 设置为非阻塞
18+
serverSocketChannel.configureBlocking(false);
19+
System.out.println("当前服务器地址:" + serverSocketChannel.socket().getLocalSocketAddress());
20+
String message = "Hello,World";
21+
ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());
22+
23+
while (true) {
24+
SocketChannel socketChannel = serverSocketChannel.accept();
25+
if (socketChannel != null) {
26+
// 当连接建立时
27+
System.out.printf("接受客户端[%s] 的连接...%n", socketChannel.getRemoteAddress());
28+
buffer.rewind();
29+
socketChannel.write(buffer); // 写入管道到发送 Socket 请求客户端
30+
socketChannel.close();
31+
32+
} else { // 非阻塞时,执行逻辑
33+
Thread.sleep(500);
34+
}
35+
}
36+
}
37+
}
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.segmentfault.deep.in.java.nio;
2+
3+
import java.nio.Buffer;
4+
import java.nio.ByteBuffer;
5+
import java.nio.CharBuffer;
6+
7+
import static com.segmentfault.deep.in.java.nio.BufferDemo.displayBufferMetadata;
8+
9+
public class CharBufferDemo {
10+
11+
public static void main(String[] args) {
12+
13+
// [X,X,X,X,X,X,X,X]
14+
// p
15+
CharBuffer buffer = CharBuffer.allocate(8);
16+
// mark(-1),position(0),limit(8),capacity(8)
17+
18+
// 当内容小于 8 字节
19+
String message = "Hello";
20+
// [X,X,X,X,X,X,X,X]
21+
// [H,e,l,l,o,X,X,X]
22+
// l
23+
// p c
24+
// flip() -> limit = position + rewind()
25+
// [H,e,l,l,o,X,X,X]
26+
// l
27+
//m p c
28+
for (char c : message.toCharArray()) {
29+
buffer.put(c);
30+
// 若不执行 flip() 操作,
31+
// rewind()
32+
// p = 0 -> limit(8) 循环
33+
}
34+
35+
displayBufferMetadata(buffer);
36+
37+
// 如果执行 flip() 操作,
38+
// limit = 8 -> 5
39+
// p = 0 -> limit(5) 循环
40+
buffer.flip();
41+
displayBufferMetadata(buffer);
42+
43+
// 依次读取 Buffer 内有效元素
44+
while(buffer.hasRemaining()) { // 循环 5 次
45+
System.out.print(buffer.get());
46+
}
47+
System.out.println(); // 有意换行
48+
49+
displayBufferMetadata(buffer);
50+
}
51+
52+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.segmentfault.deep.in.java.nio;
2+
3+
import java.io.IOException;
4+
import java.net.InetSocketAddress;
5+
import java.nio.ByteBuffer;
6+
import java.nio.channels.SelectionKey;
7+
import java.nio.channels.Selector;
8+
import java.nio.channels.ServerSocketChannel;
9+
import java.nio.channels.SocketChannel;
10+
import java.util.Date;
11+
import java.util.Iterator;
12+
import java.util.Set;
13+
14+
public class SelectorClientDemo {
15+
16+
public static void main(String[] args) throws IOException {
17+
// 客户端 SocketChannel
18+
try (SocketChannel socketChannel = SocketChannel.open();) {
19+
// 设置为非阻塞
20+
socketChannel.configureBlocking(false);
21+
// 连接服务端
22+
socketChannel.connect(new InetSocketAddress(8080));
23+
while (!socketChannel.finishConnect()) {
24+
System.out.println("等待连接到达...");
25+
}
26+
ByteBuffer buffer = ByteBuffer.allocate(8);
27+
while (socketChannel.read(buffer) != -1) {
28+
buffer.flip();
29+
while (buffer.hasRemaining()) {
30+
System.out.print(new Date(buffer.getLong()));
31+
}
32+
buffer.clear();
33+
}
34+
}
35+
}
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.segmentfault.deep.in.java.nio;
2+
3+
import java.io.IOException;
4+
import java.net.InetSocketAddress;
5+
import java.nio.ByteBuffer;
6+
import java.nio.channels.SelectionKey;
7+
import java.nio.channels.Selector;
8+
import java.nio.channels.ServerSocketChannel;
9+
import java.nio.channels.SocketChannel;
10+
import java.util.Iterator;
11+
import java.util.Set;
12+
13+
public class SelectorServerDemo {
14+
15+
public static void main(String[] args) throws IOException {
16+
// 服务端 SocketChannel
17+
try (ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();) {
18+
// 绑定服务端
19+
serverSocketChannel.socket().bind(new InetSocketAddress(8080));
20+
// 设置为非阻塞
21+
serverSocketChannel.configureBlocking(false);
22+
System.out.println("当前服务器地址:" + serverSocketChannel.socket().getLocalSocketAddress());
23+
// 打开 Selector
24+
Selector selector = Selector.open();
25+
// 注册 OP_ACCEPT
26+
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
27+
while (true) {
28+
int n = selector.select();
29+
if (n == 0) {
30+
continue;
31+
}
32+
Set<SelectionKey> keys = selector.selectedKeys();
33+
Iterator<SelectionKey> iterator = keys.iterator();
34+
while (iterator.hasNext()) {
35+
SelectionKey key = iterator.next();
36+
if (key.isAcceptable()) {
37+
ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
38+
SocketChannel socketChannel = ssc.accept();
39+
if (socketChannel == null) {
40+
continue;
41+
}
42+
System.out.printf("接受客户端[%s] 的连接...%n", socketChannel.getRemoteAddress());
43+
ByteBuffer buffer = ByteBuffer.allocate(8);
44+
// 将服务器当前 timestamp 传递到客户端
45+
buffer.putLong(System.currentTimeMillis());
46+
buffer.flip();
47+
while (buffer.hasRemaining()) {
48+
socketChannel.write(buffer);
49+
}
50+
socketChannel.close();
51+
System.out.println("当前服务器时间已发送到客户端");
52+
}
53+
iterator.remove(); // 移除已接受 SelectionKey
54+
}
55+
}
56+
}
57+
}
58+
}

0 commit comments

Comments
 (0)