当前位置: 首页 > news >正文

JAVA NIO知识点总结(6)——DatagramChannel

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

DatagramChannel——UDP数据报的通道

Java NIO中的DatagramChannel是一个能收发UDP包的通道。

操作步骤:

 打开 DatagramChannel
 接收/发送数据

用法中的一些步骤和SocketChannel类似,具体看前文博客,这里我就不说明了。

注意的是,UDP非阻塞网络,NIO中信息的接收端和发送端都是直接用DatagramChannel的open方法生成一个数据报通道,发送的时候指明地址和端口;接收的一方需要先bind一个端口号,监听着。接收方可能监听到多个发送端向其发送数据,为了单个线程能够处理多个客户端发送的数据,并且在发送的过程中不被某个发送端全程阻塞,同样需要用到选择器。

使用选择器仍然需要将通道注册到选择器上,并指明需要监听的事件,即选择键。

代码示例

package com.happybks.nio.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Date;
import java.util.Iterator;
import java.util.Scanner;

import org.junit.Test;

public class TestNonBlockingNIO2 {

	@Test
	public void send() throws IOException{
		DatagramChannel datagramChannel = DatagramChannel.open();
		datagramChannel.configureBlocking(false);
		
		ByteBuffer buf = ByteBuffer.allocate(1024);
		
		Scanner scanner = new Scanner(System.in);
		while(scanner.hasNext()){
			String inputStr=scanner.next();
			buf.put((new Date().toString()+":\n"+inputStr).getBytes());
			buf.flip();
			datagramChannel.send(buf, new InetSocketAddress("127.0.0.1", 8888));
			buf.clear();
		}
		
		scanner.close();
		datagramChannel.close();
	}
	
	@Test
	public void receive() throws IOException{
		DatagramChannel datagramChannel = DatagramChannel.open();
		datagramChannel.configureBlocking(false);

		datagramChannel.bind(new InetSocketAddress(8888));
		
		Selector selector = Selector.open();
		datagramChannel.register(selector, SelectionKey.OP_READ);
		
		while(selector.select()>0){
			Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
			
			while(iterator.hasNext()){
				SelectionKey selectionKey=iterator.next();
				if(selectionKey.isReadable()){
					ByteBuffer buf = ByteBuffer.allocate(1024);
					datagramChannel.receive(buf);
					buf.flip();
					System.out.println(new String(buf.array(), 0, buf.limit()));
					buf.clear();
				}
			}
			iterator.remove();
			
		}
		
		
	}
}

这里有一点上次没有提到,就是选择器的select()方法还有两个类似的方法。

通过Selector选择通道

一旦向Selector注册了一或多个通道,就可以调用几个重载的select()方法。这些方法返回你所感兴趣的事件(如连接、接受、读或写)已经准备就绪的那些通道。换句话说,如果你对“读就绪”的通道感兴趣,select()方法会返回读事件已经就绪的那些通道。

下面是select()方法:

int select()
int select(long timeout)
int selectNow()
select()阻塞到至少有一个通道在你注册的事件上就绪了。

select(long timeout)和select()一样,除了最长会阻塞timeout毫秒(参数)。

selectNow()不会阻塞,不管什么通道就绪都立刻返回(译者注:此方法执行非阻塞的选择操作。如果自从前一次选择操作后,没有通道变成可选择的,则此方法直接返回零。)。

select()方法返回的int值表示有多少通道已经就绪。亦即,自上次调用select()方法后有多少通道变成就绪状态。如果调用select()方法,因为有一个通道变成就绪状态,返回了1,若再次调用select()方法,如果另一个通道就绪了,它会再次返回1。如果对第一个就绪的channel没有做任何操作,现在就有两个就绪的通道,但在每次select()方法调用之间,只有一个通道就绪了。

(本文出自oschina的博主happyBKs的博文:https://my.oschina.net/happyBKs/blog/1603680)

运行结果

回到我们刚才的例子。还需要注意,每次迭代末尾的keyIterator.remove()调用。Selector不会自己从已选择键集中移除SelectionKey实例。必须在处理完通道时自己移除。下次该通道变成就绪时,Selector会再次将其放入已选择键集中。

程序运行的结果:

我们在发送端输入信息,接收端立即受到信息并输出。

221800_5SHg_1156339.png

221817_P0T5_1156339.png

 


 

转载于:https://my.oschina.net/happyBKs/blog/1603680

相关文章:

  • addEventListener()的第三个参数可以传对象了
  • 11.11. SNMP
  • [2018-01-08] Python强化周的第一天
  • Zabbix备份数据文件
  • Shell 输入/输出重定向
  • 通用汽车新增130辆测试无人车,配激光雷达
  • 了解Web及网络基础(二)
  • 拉格朗日插值
  • HomeBrew常规使用教程
  • 递归函数的写法笔记
  • mysql手写sql 建库建表示例
  • Eonasdan bootstrap datetimepicker 使用记录
  • 新版本Jenkins安装时显示离线的问题
  • WEBGL学习【十四】利用HUD技术在网页上方显示三维物体
  • Hibernate映射——多对多关联映射(八)
  • 【Redis学习笔记】2018-06-28 redis命令源码学习1
  • 08.Android之View事件问题
  • Angular 响应式表单之下拉框
  • express如何解决request entity too large问题
  • Java 网络编程(2):UDP 的使用
  • Python 反序列化安全问题(二)
  • Python十分钟制作属于你自己的个性logo
  • Python学习之路16-使用API
  • SQLServer之创建数据库快照
  • swift基础之_对象 实例方法 对象方法。
  • Transformer-XL: Unleashing the Potential of Attention Models
  • vue2.0一起在懵逼的海洋里越陷越深(四)
  • 读懂package.json -- 依赖管理
  • 给自己的博客网站加上酷炫的初音未来音乐游戏?
  • 基于Android乐音识别(2)
  • 前端相关框架总和
  • 山寨一个 Promise
  • 小程序button引导用户授权
  • 小程序开发之路(一)
  • 一个普通的 5 年iOS开发者的自我总结,以及5年开发经历和感想!
  • ​2020 年大前端技术趋势解读
  • #include到底该写在哪
  • (01)ORB-SLAM2源码无死角解析-(56) 闭环线程→计算Sim3:理论推导(1)求解s,t
  • (39)STM32——FLASH闪存
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (zt)最盛行的警世狂言(爆笑)
  • (二)正点原子I.MX6ULL u-boot移植
  • (蓝桥杯每日一题)love
  • (每日持续更新)jdk api之StringBufferInputStream基础、应用、实战
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (一)搭建springboot+vue前后端分离项目--前端vue搭建
  • (一)硬件制作--从零开始自制linux掌上电脑(F1C200S) <嵌入式项目>
  • ***原理与防范
  • .【机器学习】隐马尔可夫模型(Hidden Markov Model,HMM)
  • .net 流——流的类型体系简单介绍
  • .NET/C# 使用 #if 和 Conditional 特性来按条件编译代码的不同原理和适用场景
  • .NET关于 跳过SSL中遇到的问题
  • [100天算法】-不同路径 III(day 73)
  • [AIGC] 使用Curl进行网络请求的常见用法
  • [AMQP Connection 127.0.0.1:5672] An unexpected connection driver error occured