-
ServerSocketChannel
-
ServerSocketChannel作用?就是专职干什么的?
1、监听新进来的TCP链接通道,
2、创建新的SocketChannel
-
ServerSocketChannel 不具备 什么能力
ServerSocketChannel并不能进行数据传输的能力
-
如何创建ServerSocketChannel实例
ServerSocketChannel socketChannel =ServerSocketChannel.open();
该对象关联了一个未绑定ServerSocket的通道,
-
为ServerSocketChannel绑定监听端口号
JDK1.7前,需要调用ServerSocketChannel的socket方法,再调用bind()来进行关联
JDK1.7后,就可以直接调用ServerSocketChannel的bind()来进行端口绑定了。
-
ServerSocketChannel如何监听新进来的连接
通过 ServerSocketChannel.accept() 方法监听新进来的连接。
ServerSocketChannel 默认是 阻塞模式,可以查看JDK源码
如下,所示:
通过ServerSocketChannel.configureBlocking(true)来设定阻塞模式
1、在阻塞模式下,
如果有新的连接进来,那么accept()方法返回的是一个包含新进来的连接的SocketChannel,
如果没有新的连接,那么accept()方法,就会一直阻塞在这里,直到有的新连接进来
2、在非阻塞模式下ServerSocketChannel. configureBlocking(false)
如果有连接进来,那么accept()方法返回的是一个包含新进来的连接的SocketChannel
如果没有新的连接,那么accept()方法会立即返回null
3、阻塞模式与非阻塞模式的根本区别?
其实,就是在没有新的连接的情况下,如何处理的?不返回,一直等待的话,就是阻塞;
如果立即返回的话,就是非阻塞了。
-
SocketChannel
-
创建SocketChannel的方式?
方式一:在客户端创建
SocketChannel socketChannel = SocketChannel.open();
方式二:在服务器端创建
ServerSocketChannel接受一个连接请求后得到,如
SocketChannel socketChannel = serverSocketChannel.accept();
-
将管道中的数据读到缓存里,用的是socketChannel的read方法
int read = socketChannel.read(sizeBuffer);
-
将缓存里的数据写到管道中,用的是socketChannel的write方法
socketChannel.write(sizeBuffer);
例子如下:
服务端:
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
|
package
xingej.channel;
import
java.io.IOException;
import
java.net.InetSocketAddress;
import
java.nio.ByteBuffer;
import
java.nio.channels.ServerSocketChannel;
import
java.nio.channels.SocketChannel;
public
class
ServerSocketChannelTest {
public
void
initChannel()
throws
IOException {
//服务器端,通过open方法,来创建ServerSocketChannel
//注意,此时,服务器端,还没有进行绑定端口呢
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//设置为非阻塞模式
// serverSocketChannel.configureBlocking(false);
//绑定端口号
//JDK1.7版本之后的写法
serverSocketChannel.bind(
new
InetSocketAddress(
8081
));
//JDK1.7版本之前的写法
// serverSocketChannel.socket().bind(new InetSocketAddress(8081));
//创建字节缓存区
//缓存区的大小是1024字节,这个可以自己调试,如改成64,128....
ByteBuffer byteBuffer = ByteBuffer.allocate(
1024
);
while
(
true
) {
System.out.println(
"-------服务器端-----开始接收-----客户端的连接---------"
);
//在服务器端,接收客户端的链接,如果存在客户端的话,就返回一个
//SocketChannel对象
//如果是阻塞模式的话,没有新的链接进来,就会阻塞在这里,否则,往下执行
//如果是非阻塞模式的话,没有新的链接进来,就会立马返回一个null,程序不会阻塞在这里,
//会立马往下进行的
SocketChannel socketChannel = serverSocketChannel.accept();
if
(
null
!= socketChannel) {
while
(
true
) {
//清楚缓存区的数据,可以接收新的数据
byteBuffer.clear();
//将管道socketChannel的数据读取到 缓存byteBuffer里
//readSize 表示 读取的字节数
int
readSize = socketChannel.read(byteBuffer);
if
(readSize == -
1
) {
break
;
}
//再从 字节缓存里,进行其他 业务逻辑操作,\
// 注意,这里的缓存区使用的字节类型
// 因此,如果需要其他类型的话,需要进行转换
System.out.println(
new
String(byteBuffer.array()));
}
}
try
{
Thread.sleep(
1000
);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
}
}
public
static
void
main(String[] args)
throws
IOException {
new
ServerSocketChannelTest().initChannel();
}
}
|
客户端如下:
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
|
package
xingej.channel;
import
java.io.IOException;
import
java.net.InetSocketAddress;
import
java.nio.ByteBuffer;
import
java.nio.channels.SocketChannel;
public
class
SocketChannelTest {
public
void
connectServer()
throws
IOException{
// 创建一个 SocketChannel对象,
// 请注意,并没有进行 链接服务器端哦
SocketChannel socketChannel = SocketChannel.open();
//开始链接服务器端
socketChannel.connect(
new
InetSocketAddress(
"localhost"
,
8081
));
//在客户端创建 字节缓存区
ByteBuffer byteBuffer = ByteBuffer.allocate(
1024
);
String msg =
"\nhello, nio, hello ,spark, hello ,hadoop, flume, mesos, marathon, netty, mina, stream, inputstream, outputstream \n"
+
"hello, nio, hello ,spark, hello ,hadoop, flume, mesos, marathon, netty, mina, stream, inputstream, outputstream \n"
+
"hello, nio, hello ,spark, hello ,hadoop, flume, mesos, marathon, netty, mina, stream, inputstream, outputstream 北京\n"
;
//往字节缓存区,添加数据
byteBuffer.put(msg.getBytes());
// 针对是更新limit值,将此值更新为position了,用于接下来的读操作
byteBuffer.flip();
while
(byteBuffer.hasRemaining()) {
//将字节缓存里的数据,写到管道中去
socketChannel.write(byteBuffer);
}
socketChannel.close();
}
public
static
void
main(String[] args)
throws
IOException{
new
SocketChannelTest().connectServer();
}
}
|
启动方式:
先启动服务器端,然后再启动客户端
本文转自故新51CTO博客,原文链接:http://blog.51cto.com/xingej/1968844 ,如需转载请自行联系原作者