相关拓展:
TCP协议对应于传输层,而HTTP协议对应于应用层,从本质上来说,二者没有可比性。Http协议是建立在TCP协议基础之上的,当浏览器需要从服务器获取网页数据的时候,会发出一次Http请求。Http会通过TCP建立起一个到服务器的连接通道,当本次请求需要的数据完毕后,Http会立即将TCP连接断开,这个过程是很短的。所以Http连接是一种短连接,是一种无状态的连接。所谓的无状态,是指浏览器每次向服务器发起请求的时候,不是通过一个连接,而是每次都建立一个新的连接。如果是一个连接的话,服务器进程中就能保持住这个连接并且在内存中记住一些信息状态。而每次请求结束后,连接就关闭,相关的内容就释放了,所以记不住任何状态,成为无状态连接。
以前有个概念很容忍搞不清楚。就是为什么Http是无状态的短连接,而TCP是有状态的长连接?Http不是建立在TCP的基础上吗,为什么还能是短连接?现在明白了,Http就是在每次请求完成后就把TCP连接关了,所以是短连接。而我们直接通过Socket编程使用TCP协议的时候,因为我们自己可以通过代码区控制什么时候打开连接什么时候关闭连接,只要我们不通过代码把连接关闭,这个连接就会在客户端和服务端的进程中一直存在,相关状态数据会一直保存着。
websocket:
WebSocket 协议在2008年诞生(H5中新增协议,同样基于TCP,由通信协议和编程API组成,能够在浏览器和服务器之间建立双向链接,以基于事件方式赋予浏览器实时通信的能力,这就意味着浏览器端和服务端可以同时发送并响应请求),2011年成为国际标准。所有浏览器都已经支持了。
它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
其他特点包括:
(1)建立在 TCP 协议之上,服务器端的实现比较容易。
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
(3)数据格式比较轻量,性能开销小,通信高效。
(4)可以发送文本,也可以发送二进制数据。
(5)没有同源限制,客户端可以与任意服务器通信。
(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。
它的原生API很简单:
a. 创建ws对象:new WebSocket("ws://localhost:8090");
b. open事件: ws.onopen 建立连接时触发;
c. message事件: ws.onmessage 接收数据时触发;
d. error事件: ws.onerror 通信发生错误是触发;
e. close事件: ws.onclose 连接关闭时触发;
f. 方法: ws.send()发送数据;
g. 方法: ws.close()关闭连接;
js中内置了WebSocket构造函数,前端可以直接实例化,但是服务端使用 ws 库实现 WebSocket 协议,安装:cnpm i --save ws,利用它启动ws服务。
代码示例:
前端页面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<div class="container">
<input type="text" class="form-control" id="msg">
<button class="btn" id="send">发送信息</button>
<button class="btn" id="close">关闭</button>
<div class="box">
</div>
</div>
</body>
<script type="text/javascript">
//链接后台的ws服务
var wsObj = new WebSocket("ws://localhost:8090");
//建立连接时的事件
wsObj.onopen = function(){
console.log("链接成功")
}
var $ = document.querySelector.bind(document);
$("#send").addEventListener("click", function(){
var txt = $("#msg").value;
if(!txt){
alert("不能为空");
}else{
wsObj.send(txt);//向ws服务器发送数据
}
})
//接收后端返回的数据
wsObj.onmessage = function(data){
var p = "<p>"+data.data+"</p>";
$(".box").innerHTML += p;
}
//点击关闭按钮关闭连接
$("#close").onclick = function(){
wsObj.close();//关闭连接
}
//关闭时执行的事件
wsObj.onclose = function(){
console.log("886");
}
</script>
</body>
</html>
node页面:
var Server = require("ws").Server;//获取模块的构造函数
var ws = new Server({port: 8090});//创建ws服务的实例,并指定端口
//监听事件:
ws.on("connection", function(ws){//connection:当前端有ws请求的时候就会触发该回调,参数就是当前从前端传过来的ws对象,所以这个ws是支持message、open。。这些事件
// console.log("连接成功");
ws.on("message", function(val){//这个回调参数就是前端发送过来的数据;
ws.send(val);//再将数据返回到前端;
})
})
这些就是websocket原生api,确实很简单,前后端通用,只不过后端是自定义事件方式绑定。
但正因为原生api简单,并且只能一对一的通信,所以要做一些复杂的应用这些api就满足不了我们的需求了,不过可以通过socket.io.js这个第三方库实现,待续。。。