forked from tianshb/JavaLearning
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMultiPortEcho.java
More file actions
108 lines (86 loc) · 3.84 KB
/
Copy pathMultiPortEcho.java
File metadata and controls
108 lines (86 loc) · 3.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package com.crow;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
/**
* Created by CrowHawk on 17/9/4.
*/
public class MultiPortEcho {
private int ports[];
private ByteBuffer echoBuffer = ByteBuffer.allocate( 1024 );
public MultiPortEcho( int ports[] ) throws IOException {
this.ports = ports;
go();
}
private void go() throws IOException {
Selector selector = Selector.open();
// Open a listener on each port, and register each one
// with the selector
for (int i=0; i < ports.length; i++) {
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.configureBlocking(false);
ServerSocket ss = ssc.socket();
InetSocketAddress address = new InetSocketAddress(ports[i]);
ss.bind(address);
//将新打开的 ServerSocketChannels 注册到 Selector上,指定监听accept事件
SelectionKey key = ssc.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("Going to listen on " + ports[i]);
}
while (true) {
int num = selector.select();//返回该选择器中对I/O事件准备就绪的channel对应的key的数量
Set selectedKeys = selector.selectedKeys();//返回key的集合
Iterator it = selectedKeys.iterator();
while (it.hasNext()) {//遍历key集合,集合中的元素为SelectionKey类型
SelectionKey key = (SelectionKey) it.next();
if ((key.readyOps() & SelectionKey.OP_ACCEPT)
== SelectionKey.OP_ACCEPT) {//检查发生了什么类型的事件
// Accept the new connection
ServerSocketChannel ssc = (ServerSocketChannel)key.channel();
SocketChannel sc = ssc.accept();
sc.configureBlocking( false );
// Add the new connection to the selector
SelectionKey newKey = sc.register( selector, SelectionKey.OP_READ );//监听read事件
//Selector不会自己从已选择键集中移除SelectionKey实例。必须在处理完通道时自己移除。下次该通道变成就绪时,Selector会再次将其放入已选择键集中。
it.remove();
System.out.println( "Got connection from "+sc );
}else if ((key.readyOps() & SelectionKey.OP_READ)
== SelectionKey.OP_READ) {
// Read the data
SocketChannel sc = (SocketChannel)key.channel();
// Echo data
int bytesEchoed = 0;
while (true) {
echoBuffer.clear();
int r = sc.read( echoBuffer );
if (r<=0) {
break;
}
echoBuffer.flip();
sc.write( echoBuffer );
bytesEchoed += r;
}
System.out.println( "Echoed "+bytesEchoed+" from "+sc );
it.remove();
}
}
}
}
public static void main( String args[] ) throws Exception {
if (args.length<=0) {
System.err.println( "Usage: java MultiPortEcho port [port port ...]" );
System.exit( 1 );
}
int ports[] = new int[args.length];
for (int i=0; i<args.length; ++i) {
ports[i] = Integer.parseInt( args[i] );
}
new MultiPortEcho( ports );
}
}