经过仔细研究还是决定换回UDP协议(于是前面两天的代码滚蛋了)
NIO同样支持udp协议,不过相关的方法调用是有区别的
java的udp端口类是DatagramSocket
因此对应的nio channel类就是DatagramChannel
由于udp是一个无连接的协议,因此服务器端和客户端的代码基本相同。实际上服务器和客户端之间并没有太大区分。所以不存在ServerDatagramChannel这种玩意了,服务器端和客户端都是创建一个DatagramChannel。然后bind一个端口,注册Selector之后就可以打开监听了。
注意和SocketChannel的区别有以下几点:
接收数据:SocketChannel的方法是
ByteBuffer buffer = ByteBuffer.allocate(500);
int readCount = socketChannel.read(buffer);
虽然DatagramChannel也有read(ByteBuffer buffer)这个方法,但是直接调用只会抛出异常。
接收数据包的正确姿势如下:
ByteBuffer buffer = ByteBuffer.allocate(500);
InetSocketAddress = (InetSocketAddress)datagramChannel.receive(buffer);
此方法直接返回一个SocketAddress对象,包含了数据来源的地址和端口,在反馈数据的时候就有大用处了。于此同时,datagramChannel.getRemoteAddress()方法自然是不可能有正确结果的,没有连接是不会有Remote Address的啦
同理,发送数据包的姿势也变了
原来的方式是:
socketChannel.write(ByteBuffer.wrap("test data".getBytes()));
由于udp的无连接属性,此方法会让系统一头雾水的,我们需要加上发送的目标地址:
datagramChannel.send(ByteBuffer.wrap("test data".getBytes()),new InetAddressSocket("localhost",12345));
=======================我是傲娇的分割线================================
补充
另外,值的注意的是,在Android的开发包里,DatagramChannel的bind方法已被移除,大概是不希望某人使用一台android设备当服务器用
但是我又发现了一个connect方法,这个方法在jdk中也有,同样是传入一个SocketAddress参数。经过尝试后发现,这是android只能作为客户端的一个限定。connect方法传入的应该是服务器的地址和端口参数,调用这个connect后,android系统会自行打开一个未使用的随机端口作为发送端
这时候调用.write()方法同样可以将数据发出。注意如果这里依然调用send方法,send后的地址一定要与connect传入的地址相同,否则会报出地址不匹配的异常!
综上所述,DatagramChannel可以事先调用connect方法连接到服务器然后直接使用write发送数据
否则就必须使用send方法发送。
下图应该可以更清楚
connect(
服务器地址)--------------write()|send()
[send目标必须与connect目标相同]
bind(
本地端口)-------------------send()
[send目标可以是任意地址]
补充2
DatagramChannel不需要事先将SelectionKey的interestOps设置为OP_WRITE即可直接发送数据
=========================我才不是分割线呢==================================
注意的是与TCP基于字节流的协议不同,udp是以数据报为单位单独发送的,因此一个数据包的大小不应过大。
可通过的数据报大小由整个路径中最小的MTU决定。
[linux中可以使用ifconfig命令轻松查询到自己系统的MTU]
默认局域网MTU大小是1500字节,注意要自行减去IP数据报头20字节的占用,另外udp报头还有8个字节,也就是只有1472个字节是我们可以支配的。
超出MTU的部分会由系统进行分片处理,到达目标后再自动组装回来。但是由于udp不保证传输质量,一旦分片后某一片丢失会直接导致整个数据报被丢弃。尽管使用udp并不要求数据100%送达,但在数据完整度方面还是尽可能做到更好。
注意PPPOE/ADSL的MTU默认值是1492字节(可支配1464)
而Internet标准MTU是576字节(可支配548)
如果使用udp协议传输的数据需要经过外网,还是定义在548字节以内最佳
今天的总结就写到这里,如有谬误欢迎指正
====================
最终补充
Android慎用nio udp接收数据!!莫名其妙收不到数据报,到现在原因还没查出来。。准备客户端弃用nio了
- 大小: 35.1 KB
分享到:
相关推荐
Nio学习笔记
java NIO的基本知识点学习笔记,不包含具体代码
javaNIO学习笔记(csdn)————程序
文章同步:http://blog.csdn.net/wgyscsf/article/details/50953318
java学习笔记1(java io/nio)设计模式
NULL 博文链接:https://zheng12tian.iteye.com/blog/1094811
IO 是主存和外部设备 ( 硬盘、终端和网络等 ) 拷贝数据的过程。 IO 是操作系统的底层功能实现,底层通过 I/O 指令进行完成。 所有语言运行时系统提供执行 I/O 较高级别的工具。 (c 的 printf scanf,java 的面向对象...
JAVA NIO学习资料JAVA NIO学习资料
java_nio学习文档
UDP NIO聊天系统,基于UDP通道,NIO,包括服务器端和客户端
NIO笔记.doc
Contents: 1 核心概念以及基本读写 2 缓冲区的实现机制 3 连网与异步IO 4 分散和聚集IO 5 文件锁定
NULL 博文链接:https://copperfield.iteye.com/blog/1454238
Java NIO学习资料+代码.zip
回味Java基础之NIO!!!
主要介绍了Java NIO实例UDP发送接收数据代码分享,分享了客户端和服务端完整代码,小编觉得还是挺不错的,共需要的朋友参考。
nio学习文档及示例代码,轻松掌握nio
nio 学习 demo 解决沾包问题 处理因缓冲区满导致写入失败问题 处理因缓冲区满导致写入失败问题 ,代码里面应该在写文件结束后取消掉注册的事件
自己总结的java中NIO的笔记,绘制了详细的思维导图,每个思维导图中均有详细的博文解释,方便大家学习和理解,免费分享给大家。适合java的爱好者和学习者