WebSocket实现简易聊天室

websocket和http

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

websocket使得客户端和服务器之间的数据交换变得更加简单, 允许服务端主动向客户端推送数据.

在websocket API中, 浏览器和服务器只需要完成一次握手, 两者之间就可以直接创建持久性的连接, 并进行双向数据传输.

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

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

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

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

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

# 创建WebSocket对象
var Socket = new WebSocket(url, [protocol] );

# 第一个参数 url, 指定连接的 URL。第二个参数 protocol 是可选的,指定了可接受的子协议

WebSocket属性 :

属性 描述
Socket.readyState 只读属性readyState表示连接状态, 可以是以下值 :
  0 - 表示连接尚未建立
  1 - 表示连接已建立, 可以进行通信
  2 - 表示连接正在进行关闭
  3 - 表示连接已经关闭或者连接不能打开
Socket.bufferedAmount 只读属性 bufferedAmount已被send()放入正在队列中等待传输, 但是还没有发出的UTF-8文本字节数.

WebSocket事件 :

事件 事件处理程序 描述
open Socket.onopen 连接建立时触发
message Socket.onmessage 客户端接收服务端数据时触发
error Socket.onerror 通信发生错误时触发
close Socket.onclose 连接关闭时触发

多人聊天

建议使用火狐浏览器. 

html页面 :

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<p>发送内容: <input type="text" id="send_msg"><button onclick="send()">发送消息</button></p>
<!--用于显示聊天记录的div-->
<div id="msg_list" style=" 500px"></div>

</body>

<script>
    var ws = new WebSocket("ws://192.168.12.61:5000/ws");
    ws.onmessage = function (ws_status) {
        console.log(ws_status.data);
        var ptag = document.createElement("p");
        ptag.innerText = ws_status.data;
        document.getElementById("msg_list").appendChild(ptag)
    };
    
    function send() {
        var msg = document.getElementById("send_msg").value;
        <!--创建一个p标签-->
        var ptag = document.createElement("p");
        <!--给标签加css属性-->
        ptag.style.cssText = "text-align: right";
        <!--给p标签添加内容-->
        ptag.innerText = msg;
        <!--在div内加p标签-->
        document.getElementById("msg_list").appendChild(ptag);
        ws.send(msg);
    }
    
</script>
</html>

后端代码 :

from flask import Flask, request, render_template
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer

app = Flask(__name__)  # type:Flask
# 存放接连用户的列表
user_socket_list = []
@app.route("/ws")
def ws():
    """
    将连接的用户加入到user_socket_list列表内
    对列表循环, 将发送者发送的消息返给连接的用户(除了自己)
    :return:
    """
    # 获取连接的用户
    user_socket = request.environ.get("wsgi.websocket")
    if user_socket:
        user_socket_list.append(user_socket)
    while 1:
        # 接收发送消息者发送的消息
        msg = user_socket.receive()
        print(msg)
        # 此时user_socket是发送消息者
        for usocket in user_socket_list:
            # 排除列表内发送消息者
            if user_socket == usocket:
                continue
            try:
                # 对每一个除了自己以外的连接者发送消息
                usocket.send(msg)
            except:
                continue


@app.route("/")
def index():
    return render_template("ws.html")


if __name__ == '__main__':
    http_serv = WSGIServer(("0.0.0.0", 5000), app, handler_class=WebSocketHandler)
    http_serv.serve_forever()
原文地址:https://www.cnblogs.com/dong-/p/10175001.html