首页 > 代码库 > H5新特性websocket
H5新特性websocket
websocket也是html5的新增加内容之一,号称是下一代客户端/服务器异步通信办法,私以为虽然有点吹牛的成分,但是以后说不定能成为异步通信的半壁江山,至于取代ajax,我觉的应该不会。
websocket的一个很有意思的特点就是双向通信,这一点其实也不稀奇,跟socket一样的。
下边是websocket的原理性知识总结是写给我自己看的,如果你没兴趣,可以跳过直接到代码:
tcp建立连接tcp连接的建立需要经历”三次握手“的过程。过程如下client发送SYN包(值为j)以及SEQ包到server端,此时client进入SYN_SEND状态。此为第一次握手。server端收到SYN包后,发送一个ACK(值为seq+1)确认包和SYN(值为k)给client,此时server进入SYN_RECV状态。此为第二次握手。client收到SYN+ACK包后,向server发送一个ACK(值为k+1),该包发送完成后,client和server均进入ESTABLISH状态。此为第三次握手。
client和server两端状态变化如下:
client:
CLOSED->SYN_SEND->ESTABLISH
server:
CLOSED->LISTEN->SYN_RECV->ESTABLISH
tcp是传输层的协议,tcp三次握手后,应用层协议http也便建立了连接。而对于当今web的发展情况,http仍有许多瓶颈。
一条连接只能发送一个请求。请求只能从客户端开始。客户端不可以接收除响应以外的指令。请求/响应首部未经压缩发送,首部信息越多延迟越大。发送冗长的首部。每次互相发送相同的首部造成较多的浪费。可任意选择数据压缩格式。非强制压缩发送。虽然已经出现了很多解决方案,如ajax、comet,但是他们最终使用的都是http协议,因此也无法从根本上解决这些瓶颈。
因此也就诞生了一个新的通信协议,WebSocket协议,一种全双工通信协议。
该通信协议建立在http协议的基础之上,因此连接的发起方仍然是客户端,在http连接建立之后,再将协议升级为webSocket连接,在webSocket连接建立之后,客户度和服务器端都可以主动向对方发送报文信息了。
建立webSocket连接,需要先建立http连接,并在此基础上再进行一次”握手“。
client会发起一个”握手“的请求,请求首部含有upgrade:websocket(还有其他首部,具体看如下示例)。服务器端返回一个101状态码,确认转换协议。完成握手后便可以使用websocket协议进行通信。
Client(request)
GET /chat HTTP/1.1Host: server.example.comUpgrade: websocketConnection: UpgradeSec-WebSocket-Key: AQIDBAUGBwgJCgsMDQ4PEC==Origin: http://example.comSec-WebSocket-protocol: chat, superchatSec-WebSocket-Version: 13
server (response)
HTTP/1.1 101 switching ProtocolsUpgrade: websocketConnection: UpgradeSec-WebSocket-Accept: dGhlIHNhbXBsZSBub25jZQ==Sec-WebSocket-Protocol: chat
websocket这个协议涉及前端显示,以及服务器处理,我这里使用基础的java+js来实现一个简单的群聊
1 package example; 2 3 import java.io.IOException; 4 import java.util.Set; 5 import java.util.concurrent.CopyOnWriteArraySet; 6 7 import javax.websocket.OnClose; 8 import javax.websocket.OnError; 9 import javax.websocket.OnMessage;10 import javax.websocket.OnOpen;11 import javax.websocket.Session;12 import javax.websocket.server.PathParam;13 import javax.websocket.server.ServerEndpoint;14 15 16 @ServerEndpoint(value="http://www.mamicode.com/ws/chat/{nickName}")17 public class Chat {18 private static final Set<Chat> connections = new CopyOnWriteArraySet<Chat>();19 private String nickName; //接收用户名称20 private Session session; //建立的会话21 22 23 public Chat(){24 25 }26 27 /*28 * 打开连接29 */ 30 @OnOpen31 public void onOpen(Session session,@PathParam(value="http://www.mamicode.com/nickName") String nickName){32 this.session=session;33 this.nickName=nickName;34 connections.add(this);35 System.out.println("新用户连接进入,名字是:"+this.nickName);36 String message=String.format("System>%s %s",this.nickName,"hasjoined.");37 Chat.broadCast(message);38 39 }40 /*41 * 关闭连接42 */43 @OnClose44 public void onClose(){45 connections.remove(this);46 String message=String.format("System> %s, %s", this.nickName,47 " has disconnection.");48 Chat.broadCast(message);49 }50 51 /*52 * 接收信息53 */54 @OnMessage55 public void onMessage(String message,@PathParam(value="http://www.mamicode.com/nickName")String nickName){56 System.out.println("新消息from:"+nickName+" : "+message);57 Chat.broadCast(nickName+">"+message);58 }59 /*60 * 错误消息61 */62 @OnError63 public void one rror(Throwable throwable){64 System.out.println(throwable.getMessage());65 }66 /*67 * 广播消息68 */69 private static void broadCast(String message){70 for(Chat chat:connections){71 try{72 synchronized (chat) { //线程同步控制并发访问73 chat.session.getBasicRemote().sendText(message);74 }75 }catch(IOException e){76 connections.remove(chat);77 try{78 chat.session.close();79 80 }catch(IOException e1){81 chat.broadCast(String.format("System> %s %s", chat.nickName,82 " has bean disconnection."));83 }84 }85 }86 }87 }
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <title>Testing websockets</title> 6 </head> 7 <body> 8 <div> 9 <input type="text" id="yourName"/>10 <button id="start">click to start</button>11 </div>12 <div style="width:100%;">13 <div id="messages" style="border:5px solid red;width:50%;height:300px;margin-top:20px;"></div>14 </div>15 <div style="width:100%;margin-top:20px;">16 <div id="sends" style="float:left;width:50%;height:50px;margin-right:20px;">17 <input type="text" id="MessageUN" style="width:100%;height:48px;"/>18 </div>19 <button style="float:left;width:10%;height:50px;" id="sendMessage">发送</button>20 </div>21 22 <script type="text/javascript">23 var button=document.getElementById("start");24 button.onclick=function(){25 26 27 28 29 var name=document.getElementById("yourName");30 console.log(name.value);31 var websocketAdd="ws://localhost:8080/t8j8/ws/chat/"+name.value;32 var webSocket=new WebSocket(websocketAdd); 33 34 35 function onMessage(event) {36 document.getElementById(‘messages‘).innerHTML 37 += ‘<br />‘ + event.data;38 }39 40 function onOpen(event) {41 document.getElementById(‘messages‘).innerHTML 42 = ‘Connection established‘;43 //一旦链接开始,尝试发出一条通讯消息44 start();45 alert("消息通道开启,可以发送消息了");46 //确认链接开始,就可以开始消息的发送了47 //首先绑定一个点击事件48 var sendMessage=document.getElementById("sendMessage");49 sendMessage.onclick=function(){50 var message= document.getElementById(‘MessageUN‘).value;51 //我们之前会有一个唯一的标识符,就是在click to start之前的标识符52 webSocket.send(message);53 //上边一部完成之后,会自动触发onmessage事件54 }55 56 }57 58 59 function start() {60 webSocket.send(name.value+" : "+‘hello‘);61 }62 63 function one rror(event) {64 alert(event.data);65 }66 67 webSocket.onerror = function(event) {68 one rror(event)69 };70 71 webSocket.onopen = function(event) {72 onOpen(event)73 };74 75 webSocket.onmessage = function(event) {76 onMessage(event)77 }; 78 79 }80 81 </script>82 </body>83 </html>
重要的只有两个文件:chat.java以及chat.html,实现的是一个微型聊天室,当有用户连接近来和发送消息,所有都能看到。
H5新特性websocket