一、实现UDP单播和广播
UDP 这样的无连接协议中,并没有持久化连接这样的概念,并且每个消息(一个UDP数据报)都是一个单独的传输单元,此外UDP也没有TCP的握手机制。
通过类比,TCP连接就像打电话,其中一系列的有序消息将会在两个方向上流动,相反UDP则类似于往邮箱中投入一叠明信片;你无法知道它们将以何种顺序到达它们的目的地,或者它们是否所有的都能够到达它们的目的地。
UDP的这些方面可能会让你感觉到严重的局限性,但是它们也解释了为何它会比TCP快那么多,所有的握手以及消息管理机制的开销都已经被消除了;显然UDP很适合那些能够处理或者容忍消息丢失的应用程序,但可能不适合那些处理金融交易的应用程序。
本身作为无连接的不可靠的传输协议(适合频繁发送较小的数据包),他不会对数据包进行合并发送(也就没有Nagle算法之说了),他直接是一端发送什么数据,直接就发出去了,既然他不会对数据合并,每一个数据包都是完整的(数据+UDP头+IP头等等发一次数据封装一次)也就没有粘包一说了。
单播的传输模式,定义为发送消息给一个由唯一的地址所标识的单一的网络目的地。面向连接的协议和无连接协议都支持这种模式。
广播——传输到网络(或者子网)上的所有主机。
1、Netty的UDP相关类
interface AddressedEnvelope<M, A extends SocketAddress>extends ReferenceCounted
定义一个消息,其包装了另一个消息并带有发送者和接收者地址。其中M是消息类型;A是地址类型
class DefaultAddressedEnvelope<M, A extends SocketAddress>implements AddressedEnvelope<M,A>提供了interface AddressedEnvelope的默认实现。class DatagramPacket extends DefaultAddressedEnvelope<ByteBuf, InetSocketAddress> implements ByteBufHolder扩展了DefaultAddressedEnvelope以使用ByteBuf作为消息数据容器,DatagramPacket是final类不能被继承,只能被使用。
通过content()来获取消息内容;
通过sender();来获取发送者的消息;
通过recipient();来获取接收者的消息。
interface DatagramChannel extends Channel扩展了Netty的Channel抽象以支持UDP的多播组管理。
class NioDatagramChannnel extends AbstractNioMessageChannel implements DatagramChannel定义了一个能够发送和接收Addressed-Envelope消息的Channel类型。
Netty的DatagramPacket是一个简单的消息容器,DatagramChannel实现用它来和远程节点通信。类似于在我们先前的类比中的明信片,它包含了接收者(和可选的发送者)的地址以及消息的有效负载本身。
2、UDP单播
参见模块netty-udp下的包com.chj.udp.unicast
3、UDP广播
参见模块netty-udp下的包com.chj.udp.broadcast
二、服务器推送技术-短轮询和Comet
服务器推送技术干嘛用?就是让用户在使用网络应用的时候,不需要一遍又一遍的去手动刷新就可以及时获得更新的信息。大家平时在上各种视频网站时,对视频节目进行欢乐的吐槽和评论,会看到各种弹幕,当然,他们是用flash技术实现的,对于我们没有用flash的应用,一样可以实现弹幕。又比如在股票网站,往往可以看到,各种股票信息的实时刷新,上面的这些都是基于服务器推送技术。
具体代码参见模块netty-comet
1、Ajax短轮询
就是用一个定时器不停的去网站上请求数据。
2、Comet
“服务器推”是一种很早就存在的技术,以前在实现上主要是通过客户端的套接口,或是服务器端的远程调用。因为浏览器技术的发展比较缓慢,没有为“服务器推”的实现提供很好的支持,在纯浏览器的应用中很难有一个完善的方案去实现“服务器推”并用于商业程序。因为AJAX技术的普及,gmail等等在实现中使用了这些新技术;同时“服务器推”在现实应用中确实存在很多需求,称这种基于HTTP长连接、无须在
浏览器端安装插件的“服务器推”技术为“Comet”。
3、基于AJAX的长轮询
Spring mvc的控制层接收用户的请求之后,如果要采用异步处理,那么就要返回DeferedResult<>泛型对象,在调用完控制层之后,立即返回DeferedResult对象,此时驱动控制层的容器主线程,可以处理更多的请求。可以将DeferedResult对象作为真实响应数据的代理,而真实的数据是该对象的成员变量result,它可以是String类型,或者ModelAndView类型等。
业务处理完毕之后,要执行setResult方法,将真实的响应数据赋值到DeferedResult对象中,此时容器主线程会继续执行getResult方法,将真实数据响应到客户端。
4、SSE
严格地说