Java NIO总结(二):网络相关接口

4 篇文章 0 订阅

1.SocketChannel

SocketChannel是JavaNIO中连接到TCP网络的管道,功能和Java network包的sockt相关接口一样;有两种创建一个SocketChannel的方法:

  1. 打开一个SocketChannel连接到某个服务器
  2. 当一个ServerSocketChannel接收到请求的时候回自动创建一个SocketChannel

1.1.打开SocketChannel

SocketChannel socketChannel = SocketChannel.open();
socketChannel.connnet(new InetSocketAddress("http://www.baidu.com", 80));

1.2.关闭SocketChannel

socketChannel.close();

1.3.读取数据

ByteBuffer buffer = ByteBuffer.allocate(48);
int len = socketChannel.read(buffer);

通过前边的了解,我们对于使用buffer从channel中读取数据应该已经非常熟悉了,read()方法会返回一个整数结果表示读入数据的长度,当返回-1时表示到达数据流的终点(链接关闭)。

1.4.写入数据

String newData = "新的数据..." + System.currentTimeMillis();

ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
buf.put(newData.getBytes());

buf.flip();

while(buf.hasRemaining()) {
    channel.write(buf);
}

这里我们使用了一个循环调用write方法,因为我们并不确定write方法写入channel了多少数据,所以我们循环调用write方法直到buffer没有可写数据了。

1.5.非阻塞模式

SocketChannel可以设置为非阻塞模式(non-blocking mode),设置为非阻塞模式后,就可以使用异步模式调用connect,write,read方法了。

connect

在异步模式下,调用connet()方法后可能在链接没有建立前就返回,为了确定链接是否建立成功我们需要调用finishConnect()方法:

socketChannel.configureBlocking(false);
socketChannel.connect(new InetSocketAddress("http://localhost", 80));
while(!socketChannel.finishConnect()){
    // 等待或执行其他操作
    ...
}
write

在非阻塞模式下调用write方法可能没有任何返回值,因此我们需要循环调用write方法,就像上边的列子一样。

read

在非阻塞模式下,read方法可能不会读取出任何数据,所以我们需要关注read方法的返回值,可以通过返回值确定读取了多少数据。

2.ServerSocketChannel

ServerSocketChannel是可以监听TCP链接的通道,和Java网络包中的ServerSocket作用很相似。

下面是一个简单的例子

   // 1. 打开一个ServerSocketChannel
   ServerSocketChannel   serverSocketChannel = ServerSocketChannel.open();

   // 2. 绑定到需要监听的端口
   serverSocketChannel.socket().bind(new InetSocketAddress(9999));

   boolean listening = true;
    while(listening){

        System.out.println("listening...");

        // 3. 监听请求(阻塞,直到接收到请求)
        SocketChannel socketChannel = serverSocketChannel.accept();
        System.out.println("accept request");

        // 4. 执行其他操作  ...

        // 5. 关闭通道
        serverSocketChannel.close();
    }

ServerSocketChannel可以设置为非阻塞模式,在非阻塞模式中accept()方法立即返回,所以如果没有请求可能返回null,所以我们需要像下边的例子判断返回
SocketChannel是否为null

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(9999));
serverSocketChannel.configureBlocking(false);
while (true){
    SocketChannel socketChannel = serverSocketChannel.accept();
    if(socketChannel != null){
        // 执行操作
    }
}

3.DatagramChannel

DatagramChannel是可以接收和发送UDP数据包的Channel。因为UDP是无连接的网络连接协议,我们无法像其他channel一样使用默认的读写方法操作DatagramChannel中的数据,替代方法是send和receive数据包。

3.1.打开一个DatagramChannel

// 打开DatagramChannel
DatagramChannel channel = DatagramChanne.open();
// 绑定到UDP端口9999
channel.bind(new InetSocketAddress(9999));

3.2.接收数据

// 申请buffer
ByteBuffer buf = ByteBuffer.allocate(48);
buf.clear();
// 接收数据
channel.receive(buf);

receive()方法将复制接收到的数据到buffer中,如果接收的数据包中的数据大于buffer的容量,多余的数据则会被丢弃!

3.3.发送数据

String data = "发送数据..." + System.currentTimeMillis();
buffer.clear();
buffer.put(data.getBytes());
buffer.flip();
int sent = channel.send(buffer, new InetSocketAddress("localhost", 80));

上边代码演示了向本地UDP80接口发送数据,事实上没有应用在监听这个端口,所以什么都不会发生。由于UDP协议的无连接特性,无论发送的数据包是否被接收到,我们都不会得到反馈。

3.4.连接到特定地址

channel.connect(new InetSocketAddress("www.baidu.com", 80));

DatagramChannel可以调用connect方法链接到特定的地址,我们上面讲过UDP是无连接的协议,所以这里的链接方式并不是像TCP链接一样的真正的链接;但是它锁定了DatagramChannel使它只能向特定的地址发送和接收数据。
当链接之后DatagramChannel就可以像其他channel一样调用read()和write()方法了。

int bytesRead = channel.read(buffer);
int bytesWritten = channel.write(buffer);
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值