基于传统的前端开发,一般都使用JS访问一个URL,然后基于这个URL使用JSONDATA与URL进行交互
如下图:
最右边的CenterMaster是我们的数据接口,所有动态数据,通过这个TCP获取
那么如果要实时的展现数据的变化,那么我们有2种方法
1,使用poll(不断的轮询),这么将是一个低效的方法
2,就是在后台保持一个长连接,然后被动的触发,当有数据更新时
基于第二种,方案,我们不得不在后台打开一个原始的tcp socket连接,那么当这个TCP连接有数据接收时,那么就被动的触发了数据
所以这种方式是高效的,因为是基于事件的,而不是基于轮询的
那么在最新的HTML5里,有一个websocket的组件,能够打开一个TCP的链接,并且是异步的
但是建立websocket的,我们需要交换一些密钥来建立链接
所以我们不得不交换密钥,在链接建立之初
而HTTP是基于TCP的,所以,我们的TCP server是完全可以接收来自浏览器的HTTP的请求
例如如果,你建立一个TCP的server,绑定了192.168.1.1:8000端口
那么你在浏览器打开http://192.168.1.1:8000,返回的值就是你的outputstream里的数据
那么现在唯一个问题,就是读取浏览器的请求数据,然后交互加密密钥,那么websocket就建立成功了
浏览器请求数据如下:
GET / HTTP/1.1
Connection: Upgrade
Upgrade: websocket
Host: example.com
Origin: null
Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==
Sec-WebSocket-Version: 13
TCP-Server返回数据如下:
HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s=
Sec-WebSocket-Origin: null
Sec-WebSocket-Location: ws://192.168.1.1:8000
你的TCP server必须使用Sec-WebSocket-Key去生成
Sec-WebSocket-Accept
Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ==
如果生成错误,那么web socket将建立失败
具体生成算法如下:
Sec-WebSocket-Accept是服务器在浏览器提供的Sec-WebSocket-Key字符串后面,添加“258EAFA5-E914-47DA-95CA-C5AB0DC85B11” 字符串,然后再取sha-1的hash值
你可以参考如下代码:
Python:
from base64 import b64encode
from hashlib import sha1
GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
response_key = b64encode(sha1(key + GUID).digest())
Java:
public static String getWSSecretKey(String strWebSocketKey) {
String MAGIC_KEY = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
MessageDigest shaMD = null;
try {
strWebSocketKey = strWebSocketKey + MAGIC_KEY;
shaMD = MessageDigest.getInstance("SHA-1");
shaMD.reset();
shaMD.update(strWebSocketKey.getBytes());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
byte messageDigest[] = shaMD.digest();
BASE64Encoder b64 = new BASE64Encoder();
return b64.encode(messageDigest);
}
所以请把这些逻辑,加到你的TCPserver的链接请求的建立之初,之后并不需要再次交换这些数据
激活websocket ,在HTML里l插入一下代码
var socket = io.connect('http://192.168.1.1:8080');
或者你可以参考websocket的介绍