这篇“html5中http和Websocket的轮询与原理是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“html5中http和Websocket的轮询与原理是什么”文章吧。

一、HTTP的轮询

Web客户端与服务器之间基于Ajax(http)的常用通信方式,分为 短连接 与 长轮询 。

短连接:客户端和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接。

长轮询:客户端像传统轮询一样从服务器请求数据。然而,如果服务器没有可以立即返回给客户端的数据,则不会立刻返回一个空结果,而是保持这个请求等待数据到来(或者恰当的超时:小于ajax的超时时间),之后将数据作为结果返回给客户端。

长轮询机制如下图所示:

二、Websocket基本概念

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

现在,很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。

HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。

当你获取 Web Socket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。

三、Websocket 握手原理:

Websocket的握手原理大致可分为以下步骤:

第一步:客户端发起HTTP请求连接

第二步:服务端从请求头中取出Sec-WebSocket-Key的值

第三步:给Sec-WebSocket-Key值 拼接一个magic_string 的到一个新的value

第四步:给新的value先做 sha1加密 再做 base64加密

第五步:拼接一个响应头

第六步:服务器将拼好的响应头发送给客户端

第七步:客户端解密Sec-WebSocket-Accept得到Sec-WebSocket-Key判断是否握手成功

代码实现:

importsocket,base64,hashlib#创建socket连接sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)#绑定端地址和口号sock.bind(('127.0.0.1',9527))#监听sock.listen(5)#获取客户端socket对象conn,address=sock.accept()#获取客户端的【握手】信息data=conn.recv(1024)print(data)defget_headers(data):"""从请求头中取出Sec-WebSocket-Key对应的值并返回"""header_dict={}header_str=data.decode("utf8")foriinheader_str.split(""):ifstr(i).startswith("Sec-WebSocket-Key"):returni.split(":")[1].strip()#得到Sec-WebSocket-Key对应的值ws_key=get_headers(data)#魔法字符串magicstring为:258EAFA5-E914-47DA-95CA-C5AB0DC85B11magic_string='258EAFA5-E914-47DA-95CA-C5AB0DC85B11'#拼接socket_str=ws_key+magic_string#sha1加密socket_str_sha1=hashlib.sha1(socket_str.encode("utf8")).digest()#base64加密socket_str_base64=base64.b64encode(socket_str_sha1)#拼接响应头response_tpl="HTTP/1.1101SwitchingProtocols""Upgrade:websocket""Connection:Upgrade""Sec-WebSocket-Accept:%s""WebSocket-Location:ws://127.0.0.1:9527"%(socket_str_base64.decode("utf8"))#服务器发送响应头到客户端conn.send(response_tpl.encode("utf8"))#客户端服务端建立长连接循环接收发送数据whileTrue:msg=conn.recv(8096)print(msg)

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title></head><body></body><scripttype="text/javascript">ws=newWebSocket("ws://127.0.0.1:9527");ws.onmessage=function(ev){console.log(ev)//用于接收数据}</script></html>

附带客户端发起HTTP请求的请求头:

b'GET/ws/HTTP/1.1Host:127.0.0.1:9527Connection:UpgradePragma:no-cacheCache-Control:no-cacheUser-Agent:Mozilla/5.0(WindowsNT10.0;WOW64)AppleWebKit/537.3...Upgrade:websocketOrigin:http://localhost:63342Sec-WebSocket-Version:13Accept-Encoding:gzip,deflate,brAccept-Language:zh-CN,zh;q=0.9Sec-WebSocket-Key:kJXuOKsrl3AR1KeFngRElQ==Sec-WebSocket-Extensions:permessage-deflate;client_max_window_bits'

四、Websocket的加解密方式:

解密方式:

#b'x81x87x0exc3xf3xcd;xf6xc6xf8;xf6xc6'==========5555555hashstr=b'x81x87x0exc3xf3xcd;xf6xc6xf8;xf6xc6'#将第二个字节也就是x87第9-16位进行与127进行位运算payload=hashstr[1]&127#当位运算结果等于127时,则第3-10个字节为数据长度#第11-14字节为mask解密所需字符串#则数据为第15字节至结尾ifpayload==127:extend_payload_len=hashstr[2:10]mask=hashstr[10:14]decoded=hashstr[14:]#当位运算结果等于126时,则第3-4个字节为数据长度#第5-8字节为mask解密所需字符串#则数据为第9字节至结尾ifpayload==126:extend_payload_len=hashstr[2:4]mask=hashstr[4:8]decoded=hashstr[8:]#当位运算结果小于等于125时,则这个数字就是数据的长度#第3-6字节为mask解密所需字符串#则数据为第7字节至结尾ifpayload<=125:extend_payload_len=Nonemask=hashstr[2:6]decoded=hashstr[6:]str_byte=bytearray()foriinrange(len(decoded)):byte=decoded[i]^mask[i%4]str_byte.append(byte)print(str_byte.decode("utf8"))

加密方式:

importstructmsg_bytes="5555555".encode("utf8")token=b"x81"length=len(msg_bytes)iflength<126:token+=struct.pack("B",length)eliflength==126:token+=struct.pack("!BH",126,length)else:token+=struct.pack("!BQ",127,length)msg=token+msg_bytesprint(msg)

四、基于flask框架、Websocket协议实现的客户端和服务端链接通信示例:

pip3 install gevent-websocket

fromflaskimportFlask,requestfromgeventwebsocket.websocketimportWebSocketfromgevent.pywsgiimportWSGIServerfromgeventwebsocket.handlerimportWebSocketHandlerapp=Flask(__name__)@app.route("/ws")defwebsocket():#得到用户的链接user_socket=request.environ.get("wsgi.websocket")#type:WebSocketprint("访问成功")whileTrue:msg=user_socket.receive()#接受消息print(msg)user_socket.send(msg)#发送消息if__name__=='__main__':#指定地址、端口号开启Websocket服务http_serv=WSGIServer(("127.0.0.1",8001),app,handler_class=WebSocketHandler)#启动Websocket服务http_serv.serve_forever()

html文件:

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title><linkhref="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css"rel="stylesheet"></head><body><bottonclass="btnbtn-default"onclick="createsocket()">点击创建链接</botton><br><p>请您输入消息:<inputtype="text"placeholder="输入消息"id="msg"></p><buttomclass="btnbtn-success"onclick="send_msg()">发送消息</buttom><script>varws=null;functioncreatesocket(){ws=newWebSocket("ws://127.0.0.1:8001/ws");ws.onmessage=function(data){console.log("从服务端收到的消息=",data.data);}}functionsend_msg(){varto_msg=document.getElementById("msg").value;ws.send(to_msg)}</script></body></html>

第一步:运行flask

第二步:运行html文件

第三步:点击创建链接

第四步:输入消息

第五步:点击发送消息

客户端.png

服务器端.png

这样我们就简单实现了通过Websocket协议的客户端服务端通信。并且我们可以创建多个链接同时对服务器端通信。

五、基于Websocket实现即时通讯(IM):

服务器代码:

fromflaskimportFlask,requestfromgeventwebsocket.websocketimportWebSocketfromgevent.pywsgiimportWSGIServerfromgeventwebsocket.handlerimportWebSocketHandlerfromgeventwebsocket.exceptionsimportWebSocketErrorimportjsonapp=Flask(__name__)user_socket_dict={}@app.route("/ws/<username>")defwebsocket(username):#得到用户的链接user_socket=request.environ.get("wsgi.websocket")#type:WebSocketuser_socket_dict[username]=user_socketprint(username+"链接成功!")whileTrue:msg=user_socket.receive()#接受消息forsocketinuser_socket_dict.values():#type:WebSocketifuser_socket!=socket:#自己发消息服务器就不要再给自己回消息了try:socket.send(json.dumps({"sender":username,"msg":msg}))except:continueif__name__=='__main__':#指定地址、端口号开启Websocket服务http_serv=WSGIServer(("127.0.0.1",8001),app,handler_class=WebSocketHandler)#启动Websocket服务http_serv.serve_forever()

html代码:

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title><linkhref="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.css"rel="stylesheet"></head><body><p>请输入你的昵称:<inputtype="text"id="username"></p><bottonclass="btnbtn-default"onclick="createsocket()">点击创建链接</botton><br><p>请您输入消息:<inputtype="text"id="msg"></p><buttomclass="btnbtn-success"onclick="send_msg()">发送消息</buttom><br><br><br><divid="text_div"></div><script>varws=null;varusername=null;functioncreatesocket(){username=document.getElementById("username").value;ws=newWebSocket("ws://127.0.0.1:8001/ws"+"/"+username);ws.onmessage=function(data){vartext_div=document.getElementById("text_div");varobj_data=JSON.parse(data.data);varadd_msg="<p>"+obj_data.sender+":"+obj_data.msg+"</p>";text_div.innerHTML+=add_msg;}}functionsend_msg(){varto_msg=document.getElementById("msg").value;vartext_div=document.getElementById("text_div");varadd_msg="<pstyle='text-align:right'>"+to_msg+":"+username+"</p>";text_div.innerHTML+=add_msg;ws.send(to_msg);}</script></body></html>

第一步:运行flask服务器

第二步:运行html文件

第三步:输入昵称,点击创建链接

第四步:输入消息

第五步:点击发送消息

以上就是关于“html5中http和Websocket的轮询与原理是什么”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注亿速云行业资讯频道。