1.什么是websocket
websocket
是HTML5
出的协议,和HTTP协议没有什么关系,它的目的在于,在浏览器和服务器之间建立一个不受限制的双向实时通信的通道,比如服务器可以任意时刻向浏览器主动的推送消息它基于TCP,先通过HTTP/
HTTPS
协议发起一条特殊的HTTP请求进行握手后创建一个用于交换数据的TCP连接他们是并行的关系
HTTP和WebScoket
的区别
- HTTP不支持常久的连接(长连接\循环连接等不算)
WebScket
和服务器只要一次握手动作,HTTP协议每次链接都需要三次握手才能发送消息- 服务器和浏览器都可以在任意时刻相互的推送消息,HTTP的缺点就在于此,浏览器不主动请求,服务器就没法给浏览器发送数据
- HTTP协议每次请求都要发送请求头,
websocket
一旦建立连接,之后请求都不用发送请求头
虽然HTTP可以用轮询或者comet机制实现
WebSocket
的功能,但是,每次轮询,就算是再快,也需要间隔时间,这样就造成了它的实时性不够,而且, 频繁的发送请求,会给服务器造成很大的压力,一般情况下,没人会这么做
- 轮询:
js
启动定时发送请求,间隔性的请求服务器是否有新的数据 - comet:请求没有超过预定时间或者没有返回数据,一直保持连接状态,等有了数据再进行推送
comet虽然是实时性够了,但是,长时间挂起线程,会浪费服务器的资源,如果长时间没有数据,链路上的任何一个网关都可能关闭这个链接。
所以,会造成两个后果,要么,你不知道什么时候断开了,要么,你就定期发ping,检查连接是否正常
2.什么是三次握手,四次挥手
这是基于TCP协议的规则,建立TCP需要三次握手才能建立,而断开连接则需要四次挥手
三次握手
第一次握手,客户端发送一个待SYN表之的TCP报文到服务器
第二次握手,服务器回应客户端,发送一个带有SYN和ACK
标志的报文,表示它对客户端SYN报文的回应,同时询问客户端是否准备好进行数据通讯
第三次握手,客户端必须再次回应服务器一个ACK
报文
四次挥手
第一次挥手,客户端发送一个FIN,用来关闭客户到服务器的数据传送
第二次挥手,服务器收到这个FIN,它发回一个ACK
,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。
第三次挥手,服务器关闭客户端的连接,发送一个FIN给客户端
第四次挥手,客户段发回ACK
报文确认,并将确认序号设置为收到序号加1
由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
3.WebSocket
的使用
1.首先需要一个dwebsocket
依赖,安装非常简单,直接pip install dwebsocket
2.在settings
中需要注册加载,INSTALLED_APPS
注册dwebsocket
dwebsocket
在django3.1
之后自动加载,在这之前,都需要进行注册这一步骤
3.导包from dwebsocket.decorators import accept_websocket
4.写一个视图函数,需要用**@accept_websocket
**,这样,声明了他是一个webscoket
连接,这只是链接,不是发送消息,这里,定义了一个公共字典clients,一会儿要用,记住它
clients = {{
@accept_websocket
def websocketlink(request):
if request.is_websocket():
userid = uuid.uuid1()
while True:
message = request.websocket.wait()
if not message:
break
else:
clients[userid] = request.websocket
dwebsocket
有两种装饰器:require_websocket
和accept_websocekt
使用require_websocket
装饰器会导致视图函数无法接收导致正常的http
请求,一般情况使用accept_websocket
方式就可以了
5.在前端,发送一个连接,注意,此时后端的链接不是http
,而是ws
// websocket连接
if('WebSocket' in window){
// 生成websocket链接
var ws = new WebSocket('ws://127.0.0.1:8000/websocketlink/');
// 发送链接
ws.onopen = function(){
ws.send('你好啊世界');
{
// 发送消息
ws.onmessage=(evt)=>{
// 将获取信息打印
var received_msg = evt.data;
this.$notification.open({
message:received_msg
{)
ws.onclose = function(){
console.log('链接已关闭')
{
{
6.推送消息接口,一个函数视图举例:
def sendmessage(request):
# 获取消息
msg = request.GET.get('msg')
# 循环公共字典clients,遍历内部所有的链接,
for client in clients:
clients['client'].send(msg.encode('utf-8'))
return HttpResponse({'message':"ok"{)
然后,链接成功后,再新打开一个页面,访问这个sendmessage
方法,就可以在你的前端页面看到你发送的数据啦
- Post link: https://www.godhearing.cn/websocket/
- Copyright Notice: All articles in this blog are licensed under unless otherwise stated.