• V3_699843
    了解作者
  • 10.2KB
    文件大小
  • rar
    文件格式
  • 0
    收藏次数
  • VIP专享
    资源类型
  • 0
    下载次数
  • 2022-06-08 06:30
    上传日期
NULL 博文链接:https://bruce-king.iteye.com/blog/2095677
content.rar
  • content.txt
    25.7KB
内容介绍
{toc-table} h1. 〇 Apusic与WebSocket 是的,Apusic现已集成了WebSocket,集成的是JSR 356的参考实现Tyrus 1.7,能运行在JDK6及以上的环境。预计Apusic v9.0 sp2的发布就会带上WebSocket,所以就废话不啰嗦了,马上看看什么葫芦卖什么药。 ---- h1. 一 WebSocket协议 —— RFC 6455 WebSocket伴随着HTML5的大潮到来,其前身是Adobe Flash中的内嵌Socket,经过好几次主要的草案版本的修改后,终于稳定在RFC 6455的version 13,在各大主流的浏览器均已稳定支持一段时间了。 有鉴于此,Apusic对WebSocket进行集成支持。 之所以叫WebSocket,因为它是通过HTTP的Web报头进行握手才建立的Socket链接。使用它便可以跳出HTTP一来一回的半双工的工作模式,可以按照类似普通Socket的编程方式在客户端与服务器端进行随时随地的全双工通信了。 下面会描述一下WebSocket协议的一些关键位置,有能力的同学可以直接上http://tools.ietf.org/html/rfc6455,而只关心WebSocket JavaEE程序怎么写的同学可以直接跳到下一章。 h2. 一·〇 握手过程 稍微清楚TCP的工作方式的程序员都知道,TCP Socket间在建立链接前,是需要“三次握手”进行确认的(暂时忽略TCP Fast Open/Recovery)。这样的握手过程能够确保通信的两端的稳定存在,也可以利用这个握手过程自适应地找出TCP RTT的各个参数的有效值。 WebSocket也有类似的握手过程,但是它与TCP握手的方式是完全不同的: # TCP在进行握手前,通信的两端尚未建立链接;而WebSocket要进行握手,通信的两端其实已经存在一个HTTP链接了(当然也就是已存在一个TCP链接)。 # TCP Socket的可以在通信的任意一端发起握手;而WebSocket只能在HTTP协议订明的客户端发起握手。 # TCP握手是基于二进制格式的,一般情况下过程有三步;而WebSocket握手是基于HTTP报头的(即基于文本),任何情况下都有两步过程。 顺带一提,类似TCP握手过程中会被利用来作DDoS或者反射攻击的问题不会出现在WebSocket握手上,因为它们根本就是两个不同层次的握手过程。 所以,不要混淆这两个东西。 WebSocket具体的握手过程如下: 1、HTTP客户端给服务器发送一个带着HTTP链接升级(Connection: upgrade)报头的GET请求到服务器端: {code} GET /chat HTTP/1.1 Host: server.example.com Connection: upgrade Upgrade: websocket Origin: http://server.example.com Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== Sec-WebSocket-Version: 13 {code} 2、假定服务器server.example.com的/chat路径的确是一个WebSocket路径,它在接收到该请求后,便会返回一个状态为101的协议切换响应头,并保持该HTTP链接对应的TCP Socket一直打开,以便双方通信: {code} HTTP/1.1 101 Switching Protocols Connection: upgrade Upgrade: websocket Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= {code} 另外需要注意报头中还有两处必须注意: * Origin报头必须保证与服务器端同源,不同源的话服务器会返回403拒绝访问,至于是否同源的判断在另外一份RFC规范中有详细描述:http://tools.ietf.org/html/rfc6454#section-3.2。 * Sec-WebSocket-Key报头是客户端发给服务器端的一个“挑战值”——实际上是一个随机二进制数组的Base64编码字符串,服务器端接收到这个值,必须对其进行一些运算才能生成对应的Sec-WebSocket-Accept报头,具体运算规则为:Sec-WebSocket-Accept = Base64.encode(SHA-1(String.concat(Sec-WebSocket-Key, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"))),后面那串“258EAF…”是一个“魔法串”,是一个经过RFC 4122规范分配出来的GUID常量,具体值为什么是它就不必深究了。 如果需要权威的协议握手描述,或者需要清楚握手失败等异常情况客户端、服务器端应该作什么处理,请参考:http://tools.ietf.org/html/rfc6455#section-4。 h2. 一·一 协议的扩展性 握手过程就正如上面描述的简单,但是它还是具有一定的扩展性,只需要客户端发起握手时在报头添加Sec-WebSocket-Protocol或者Sec-WebSocket-Extensions。 h3. 一·一·〇 Sec-WebSocket-Protocol Sec-WebSocket-Protocol报头可以让客户端指定它希望服务器以什么样子协议(subprotocol)处理这个WebSocket链接的内容,一般来说客户端会提供一系列的候选值: {code} GET /chat HTTP/1.1 …… Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Key: …… …… {code} 如果服务器端认可这些子协议中的某个,则可以返回: {code} HTTP/1.1 101 Switching Protocols …… Sec-WebSocket-Protocol: chat Sec-WebSocket-Accept: …… …… {code} 当然,这些子协议间如果有优先级的差别,客户端在填写该报头的时候需要按从高优先级至低的顺序填写这些值,并以逗号分隔。例如例子中的chat子协议优先级就比superchat的高,服务器应该优先匹配chat子协议。(啰嗦了这么多,其实就是与HTTP的Accept/Accept-Encoding报头的处理类似。) 另外,Sec-WebSocket-Protocol的值原则上是可以由客户端任意填写的,但是为了规范协议的行为,有些子协议名称其实已经在IANA上注册,如果不想服务器错误地运作,最好还是不要乱填(或者干脆不填,这是现在的普遍做法),如果真的想利用这个报头,最好还是先翻查一下:http://www.iana.org/assignments/websocket/websocket.xhtml#subprotocol-name。 最后,其实暂时没多少通用服务器会处理子协议协商,一般来说不论客户端发出什么,现时多数的通用服务器都会不返回任何Sec-WebSocket-Protocol报头——也就是不作任何协商,除非服务器上的应用程序有处理。某些特殊的服务器会处理它,其实假以时日WebSocket应用多了,通用服务器就会对它做协商的了,就像当年的Web Gzip格式一样。 h3. 一·一·一 Sec-WebSocket-Extensions Sec-WebSocket-Extensions报头的协商方式与前面的Sec-WebSocket-Protocol一样,但是有个比较不一样的地方就是IANA暂时没有注册任何标准Extensions名字,貌似也不打算让厂商注册。也就是说这个报头协商出来的扩展完全是预留给程序员自己处理的,例如我们可以自己协商一些类似加密、压缩内容之类的扩展,这样就可以在WebSocket中做到较好的通信安全性(当然,要通讯安全首选还是在HTTPS上再进行WebSocket握手)。 如果感觉自己写的WebSocket协议扩展有种莫名的山寨感,就不要考虑用Sec-WebSocket-Protocol报头了,直接用Sec-WebSocket-Extensions报头吧。 还需要一提的是,Sec-WebSocket-Extensions报头协商好之后,这些扩展是可以利用WebSocket数据帧(Frame)中的一些预留位进行特殊数据处理的,这一部分是Sec-WebSocket-Protocol没有的,这也是为什么还是强烈建议使用它的原因——不怕冲突之余还有额外的扩展辅助。 不过与Sec-WebSocket-Protocol一样,暂时没什么通用服务器会处理Sec-WebSocket-Extensions报头,而且以后也不会有,因为这个报头完全就是留给应用程序的,服务器本身不应该处理它。 h2. 一·二 帧格式 在WebSocket上传输的数据是一帧一帧那样传输的,这就像TCP的数据也是一段一段那样封装成IP报文那样在网络上传输那样。要注意,由于WebSocket是基于TCP之上的协议,所以它自身不需要像TCP协议那样关注传输的顺序、重排与滑动窗口控制,只要其中一端是按顺序在WebSocket发送数据帧,接收的一端肯定是会按顺序地接收到�
评论
    相关推荐