博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java NIO 之 ServerSocketChannel 与 SocketChannel
阅读量:6814 次
发布时间:2019-06-26

本文共 4416 字,大约阅读时间需要 14 分钟。

  • 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 ,如需转载请自行联系原作者

你可能感兴趣的文章
oracle系统用户详解
查看>>
从优化业务流程谈信息化管理
查看>>
Android系统编译系统分析大全(二)
查看>>
git学习
查看>>
一篇笔记整理JVM工作原理
查看>>
ETL大数据测试介绍
查看>>
利用tar 通过网络拷贝数据
查看>>
CSS中的绝对定位与相对定位
查看>>
ubuntu 修改系统时间
查看>>
Struts2页面到action的三种传值方式
查看>>
【算法导论】插入排序
查看>>
html5定位getLocation()
查看>>
centos7生产环境下openssh升级
查看>>
[原创]Win2003+IE8+VS2005不能进入调试状态
查看>>
[HNOI2004]宠物收养场
查看>>
BZOJ3781:小B的询问(莫队)
查看>>
Ruby实现wordCounter
查看>>
SOAP Services for Python
查看>>
js判断处理undefined类型的数据
查看>>
经验&&bug
查看>>