websocket是HTML5出的一个新的网络通讯协议,与HTTP协议没有关系。它们俩能够说是独立的两个协议,可是也会有一些共同点。javascript
HTTP 协议是一种无状态的、无链接的、单向的应用层协议。它采用了请求/响应模型。通讯请求只能由客户端发起,服务端对请求作出应答处理。css
这种通讯模型有一个弊端:HTTP 协议没法实现服务器主动向客户端发起消息。html
这种单向请求的特色,注定了若是服务器有连续的状态变化,客户端要获知就很是麻烦。大多数 Web 应用程序将经过频繁的异步JavaScript和XML(AJAX)请求实现长轮询。轮询的效率低,很是浪费资源(由于必须不停链接,或者 HTTP 链接始终打开)。前端
它是一个非持久化的协议,还有着有版本之分,有1.0,1.1,它的生命周期有Request来界定,在1.0版本中,一次请求,一次响应,那么此次请求就结束了。可是如今主流版本已是1.1了,对于这种请求也有了改进,能够实现长链接,也就是说在一个HTTP当中能够发送多个请求,接收多个响应,可是必定要明确的一个点,必须一个请求对应一个响应,并且必须先请求,才能返回响应
WebSocket 是 HTML5 开始提供的一种在单个 TCP 链接上进行全双工通信的协议。java
websocket是一个基于HTTP的网络协议,它和HTTP最主要的区别就是它比较持久web
pip install flask
pip install gevent-websocket
聊天室功能使用了flask来进行模板,url之类的解析,不一样之处是再也不使用flask自带的容器,而是看成一个应用,被gevent里的一个uwsgiserver容器来调用json
知识补充:flask
// 新建一个websocket连接 var s = new WebSocket("%s://%s/foobar/"); s.onopen = function() {} // 接收后端发送过来的数据 s.onmessage = function(e) {} s.onerror = function(e) {} // s.onclose = function(e) {} // 发送数据 s.send(value);
后端:bootstrap
from flask import Flask, request, render_template from geventwebsocket.websocket import WebSocket from geventwebsocket.handler import WebSocketHandler from gevent.pywsgi import WSGIServer import json app = Flask(__name__) @app.route("/index") def index(): return render_template("ws.html") user_socket_dict = {} @app.route("/ws/<username>") def ws(username): user_socket = request.environ.get("wsgi.websocket") # type: WebSocket if not user_socket: return "使用WebSocket方式链接" user_socket_dict[username] = user_socket print(user_socket_dict) while True: try: # 接收客户端传入数据 user_msg = user_socket.receive() # 将以用户名为键,链接为值的字典迭代出全部的键值对 for k,v in user_socket_dict.items(): # 将当前发送数据的用户以及数据放在一块儿组成字典 # print(v) who_send_msg = { "send_user": username, "send_msg": user_msg } # print(who_send_msg) # 若是当前链接与迭代出来的链接相同,就跳过本次循环 if user_socket == v: continue # 不然 将用户以及用户数据以json格式发送出去 v.send(json.dumps(who_send_msg)) except Exception as e: # 当捕捉到异常的时候就将当前用户从字典中删除 user_socket_dict.pop(username)if __name__ == '__main__': http_serv = WSGIServer(("0.0.0.0",8000),app,handler_class=WebSocketHandler) http_serv.serve_forever()
前端代码:后端
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <style> #chat_window { width: 450px; height: 450px; border: 1px solid black; border-radius: 20px; margin: 30px auto; } .span_div { margin: 25px; font-size: 18px; } .chat_span { font-size: 28px; border: 2px solid red; border-radius: 20px; } </style> </head> <body> <div class="container"> <h2 style="text-align: center">websocket聊天室</h2> <div class="row"> <div class="panel panel-info col-lg-6 col-lg-offset-3"> <div class="panel-heading">微信</div> <div class="panel-body"> <div style="text-align: center"> <label for="username">自报家门:</label> <input type="text" id="username"> <label for="to_username">发送目标:</label> <input type="text" id="to_username"> <button class="btn btn-danger" id="create_ws" onclick="go_to()">建立ws链接 </button> </div> <div id="chat_window"> </div> <div class="col-lg-12"> <div class="input-group"> <input type="text" class="form-control" id="send_msg"> <span class="input-group-btn"> <button class="btn btn-success" type="button" id="btn_send">发送</button> </span> </div><!-- /input-group --> </div><!-- /.col-lg-6 --> </div><!-- /.row --> </div> </div> </div> </div> </body> <script type="application/javascript"> var ws_url = "ws://127.0.0.1:8000/ws/"; var ws = null; function go_to() { var username = document.getElementById("username"); // 将用户参数和url路径一块儿组成新的url ws = new WebSocket(ws_url + username.value); console.log(ws); // 接收后端传入的信息 ws.onmessage = function (serv_msg) { msg = JSON.parse(serv_msg.data); console.log(msg); creat_chat('y', msg); }; } // 添加聊天记录 function creat_chat(self, content) { if (self == 'w') { self = 'right'; // 将本身的聊天记录放入span标签 var span_tag = document.createElement('span'); span_tag.innerText = content.send_msg; // 将用户名放入span标签 var span_tag1 = document.createElement('span'); span_tag1.innerText = ":我"; span_tag1.setAttribute('class', 'chat_span') } else { self = 'left'; // 将好友的聊天记录放入span标签 var span_tag = document.createElement('span'); span_tag.innerText = content.send_user + ":"; span_tag.setAttribute('class', 'chat_span'); // 将用户名放入span标签 var span_tag1 = document.createElement('span'); span_tag1.innerText = content.send_msg; } // 建立一个大的div标签 var div_tag = document.createElement('div'); div_tag.setAttribute('class', 'span_div'); // 修改样式 div_tag.style = 'text-align:' + self; // 将聊天记录和用户名添加进来 div_tag.appendChild(span_tag); div_tag.appendChild(span_tag1); var chat_window = document.getElementById('chat_window'); chat_window.appendChild(div_tag) } // 事件监听 ,点击发送按钮要执行的代码 document.getElementById("btn_send").addEventListener("click", function () { // 取出你输入框里面的数据 var send_msg = document.getElementById("send_msg"); // 获取发送目标标签对象 var to_user = document.getElementById("to_username"); // 组成发送字典 send_msg_json = { send_msg: send_msg.value, to_user: to_user.value }; // 将字典进行序列化并发送 ws.send(JSON.stringify(send_msg_json)); var s_msg = {send_msg: send_msg.value}; creat_chat("w", s_msg); send_msg.value = '' }) </script> </html>
from flask import Flask, request, render_template from geventwebsocket.websocket import WebSocket from geventwebsocket.handler import WebSocketHandler from gevent.pywsgi import WSGIServer import json app = Flask(__name__) @app.route("/index2") def index(): return render_template("ws_one.html") user_socket_dict = {} @app.route("/ws/<username>") def ws(username): user_socket = request.environ.get("wsgi.websocket") # type: WebSocket if not user_socket: return "使用WebSocket方式链接" user_socket_dict[username] = user_socket while True: try: # 接收客户端传入数据 user_msg = user_socket.receive() user_msg = json.loads(user_msg) to_user_socket = user_socket_dict.get(user_msg.get("to_user")) # 将当前发送数据的用户以及数据放在一块儿组成字典 send_msg = { "send_user": username, "send_msg": user_msg.get("send_msg") } to_user_socket.send(json.dumps(send_msg)) except WebSocketHandler as e: # 当捕捉到异常的时候就将当前用户从字典中删除 user_socket_dict.pop(username) print(e) print(user_socket_dict) if __name__ == '__main__': http_serv = WSGIServer(("0.0.0.0",8000),app,handler_class=WebSocketHandler) http_serv.serve_forever()
前端代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <style> #chat_window { width: 450px; height: 450px; border: 1px solid black; border-radius: 20px; margin: 30px auto; } .span_div { margin: 25px; font-size: 18px; } .chat_span { font-size: 28px; border: 2px solid red; border-radius: 20px; } </style> </head> <body> <div class="container"> <h2 style="text-align: center">websocket聊天室</h2> <div class="row"> <div class="panel panel-info col-lg-6 col-lg-offset-3"> <div class="panel-heading">微信</div> <div class="panel-body"> <div style="text-align: center"> <label for="username">自报家门:</label> <input type="text" id="username"> <label for="to_username">发送目标:</label> <input type="text" id="to_username"> <button class="btn btn-danger" id="create_ws" onclick="go_to()">建立ws链接 </button> </div> <div id="chat_window"> </div> <div class="col-lg-12"> <div class="input-group"> <input type="text" class="form-control" id="send_msg"> <span class="input-group-btn"> <button class="btn btn-success" type="button" id="btn_send">发送</button> </span> </div><!-- /input-group --> </div><!-- /.col-lg-6 --> </div><!-- /.row --> </div> </div> </div> </div> </body> <script type="application/javascript"> var ws_url = "ws://127.0.0.1:8000/ws/"; var ws = null; function go_to() { var username = document.getElementById("username"); // 将用户参数和url路径一块儿组成新的url ws = new WebSocket(ws_url + username.value); console.log(ws); // 接收后端传入的信息 ws.onmessage = function (serv_msg) { msg = JSON.parse(serv_msg.data); console.log(msg); creat_chat('y', msg); }; } // 添加聊天记录 function creat_chat(self, content) { if (self == 'w') { self = 'right'; // 将本身的聊天记录放入span标签 var span_tag = document.createElement('span'); span_tag.innerText = content.send_msg; // 将用户名放入span标签 var span_tag1 = document.createElement('span'); span_tag1.innerText = ":我"; span_tag1.setAttribute('class', 'chat_span') } else { self = 'left'; // 将好友的聊天记录放入span标签 var span_tag = document.createElement('span'); span_tag.innerText = content.send_user + ":"; span_tag.setAttribute('class', 'chat_span'); // 将用户名放入span标签 var span_tag1 = document.createElement('span'); span_tag1.innerText = content.send_msg; } // 建立一个大的div标签 var div_tag = document.createElement('div'); div_tag.setAttribute('class', 'span_div'); // 修改样式 div_tag.style = 'text-align:' + self; // 将聊天记录和用户名添加进来 div_tag.appendChild(span_tag); div_tag.appendChild(span_tag1); var chat_window = document.getElementById('chat_window'); chat_window.appendChild(div_tag) } // 事件监听 ,点击发送按钮要执行的代码 document.getElementById("btn_send").addEventListener("click", function () { // 取出你输入框里面的数据 var send_msg = document.getElementById("send_msg"); var to_user = document.getElementById("to_username"); send_msg_json = { send_msg:send_msg.value, to_user:to_user.value }; ws.send(JSON.stringify(send_msg_json)); var s_msg = {send_msg: send_msg.value}; creat_chat("w", s_msg); send_msg.value = '' }) </script> </html>