zoukankan      html  css  js  c++  java
  • flask之gevent-websocket的IO多路复用长连接通信

    本节目录:

    (一)笔记总结;

    (二)gevent-websocket+flask+javascript实现WS即时通信

      (1)无昵称群聊

      (2)有昵称群聊

      (3)私聊

    三种通信模型简述: 

    (1)轮询:
    客户端周期性不间断高频率的给服务器发送请求:
    客户端请求--服务器响应--断开连接,请求次数QPS比较频繁,对客户端和服务器的配置要求比较高
    (2)长轮询:
    客户端周期性不间断的给服务器发送请求:
    客户端与服务器建立的连接会保持一定时间,因此请求相对不会特别频繁
    (3)长连接:
    客户端与服务端建立连接后,如果不是特殊原因(客户端主动断开,服务器故障)连接会一直保持
    同时通过多线程进行IO多路复用技术解决并发问题

    flask中基于gevent-websocket的IO多路复用技术进行长连接通信:  

    (1)基于gevent-websocket的IO多路复用长连接通信,需要导入一下模块:
    #pip install gevent-websocket导入IO多路复用模块
            from geventwebsocket.handler import WebSocketHandler         #提供WS(websocket)协议处理
            from geventwebsocket.server import WSGIServer                #websocket服务承载
            #WSGIServer导入的就是gevent.pywsgi中的类
            # from gevent.pywsgi import WSGIServer
            from geventwebsocket.websocket import WebSocket              #websocket语法提示
    (2)路由视图函数中的处理必须通过request.environ.get('wsgi.websocket')获取与客户端的ws连接client_socket:
     #websocket协议通信如下(http请求正常处理即可)
            @app.route()
            def func():
                client_socket=request.environ.get('wsgi.websocket')
                while 1:
                    client_socket.recive()
                        ...
                    client_socket.send(str)
                        ...
    (3)flask项目启动如下:
    WSGIServer默认处理的是http请求,路由视图中可以正常使用http,
    但是在使用ws协议时务必在视图函数通过request.environ.get('wsgi.websocket')获取与客户端的ws连接client_socket,
    通过连接client_socket进行client_socket.recive()/client_socket.send()通信,这连个方法会对字符串自动进行编解码)
    http_server=WSGIServer(('192.168.16.14',8888),application=app,handler_class=WebSocketHandler。
    http_server.serve_forever()
    (4)前端页面使用js进行WS(websocket)请求:
    浏览器提供了websocket客户端,直接new创建websocket连接ws,
    (ws状态码0表示已创建未连接,1表示已连接保持中,2表示客户端主动断开连接,3表示服务端断开连接),
    通过ws.onmessage=function (MessageEvent){}监听执行回调函数获取信息MessageEvent.data,
    通过ws.send()发送信息。
    <script>
        var ws = new WebSocket('ws://192.168.16.14:8888/websocket');
        ws.onmessage = function (MessageEvent) {
            console.log(MessageEvent);
            console.log(MessageEvent.data);        
        };
    
        function send() {
            var msg = document.getElementById('msg').value;
            ws.send(msg);
        }
    </script>

    http请求协议和websocket请求协议的请求原数据request.environ和请求头部信息request.headers比较:
    http-environ:

    {
         'GATEWAY_INTERFACE': 'CGI/1.1', 'SERVER_SOFTWARE': 'gevent/1.4 Python/3.6', 
         'SCRIPT_NAME': '', 'wsgi.version': (1, 0), 
         'wsgi.multithread': False, 'wsgi.multiprocess': False, 
         'wsgi.run_once': False, 'wsgi.url_scheme': 'http', 
         'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>, 
         'SERVER_NAME': 'PC-Yang', 'SERVER_PORT': '8888', 'REQUEST_METHOD': 'GET', 
        'PATH_INFO': '/websocket', 'QUERY_STRING': '', 'SERVER_PROTOCOL': 'HTTP/1.1', 
        'REMOTE_ADDR': '192.168.16.14', 'REMOTE_PORT': '61539', 'HTTP_HOST': '192.168.16.14:8888', 
        'HTTP_CONNECTION': 'keep-alive', 'HTTP_PRAGMA': 'no-cache', 'HTTP_CACHE_CONTROL': 'no-cache', 
        'HTTP_UPGRADE_INSECURE_REQUESTS': '1', 
        'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36', 
        'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3', 
        'HTTP_ACCEPT_ENCODING': 'gzip, deflate', 'HTTP_ACCEPT_LANGUAGE': 'zh-CN,zh;q=0.9', 
        'wsgi.input': <gevent.pywsgi.Input object at 0x03A9DC00>, 
         'wsgi.input_terminated': True, 'werkzeug.request': <Request 'http://192.168.16.14:8888/websocket' [GET]>
        }
    http-environ

    http-headers:

    '''
        Host: 192.168.16.14:8888
        Connection: keep-alive
        Pragma: no-cache
        Cache-Control: no-cache
        Upgrade-Insecure-Requests: 1
        User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
        Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
        Accept-Encoding: gzip, deflate
        Accept-Language: zh-CN,zh;q=0.9
    '''
    http-headers

    websocket-environ: 'wsgi.websocket': <geventwebsocket.websocket.WebSocket object at 0x03A9DC00>,websocket连接

    '''
        {
         'GATEWAY_INTERFACE': 'CGI/1.1', 'SERVER_SOFTWARE': 'gevent/1.4 Python/3.6', 
         'SCRIPT_NAME': '', 'wsgi.version': (1, 0), 'wsgi.multithread': False, 
         'wsgi.multiprocess': False, 'wsgi.run_once': False, 'wsgi.url_scheme': 'http', 
         'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>, 
         'SERVER_NAME': 'PC-Yang', 'SERVER_PORT': '8888', 'REQUEST_METHOD': 'GET', 
        'PATH_INFO': '/websocket', 'QUERY_STRING': '', 'SERVER_PROTOCOL': 'HTTP/1.1', 
        'REMOTE_ADDR': '192.168.16.14', 'REMOTE_PORT': '61591', 'HTTP_HOST': '192.168.16.14:8888', 
        'HTTP_CONNECTION': 'Upgrade', 'HTTP_PRAGMA': 'no-cache', 'HTTP_CACHE_CONTROL': 'no-cache', 
        'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36', 
        'HTTP_UPGRADE': 'websocket', 'HTTP_ORIGIN': 'http://192.168.16.14:8888', 'HTTP_SEC_WEBSOCKET_VERSION': '13', 
        'HTTP_ACCEPT_ENCODING': 'gzip, deflate', 'HTTP_ACCEPT_LANGUAGE': 'zh-CN,zh;q=0.9', 
        'HTTP_SEC_WEBSOCKET_KEY': 'Oyfq0MCEBnsypKstjjRvYg==', 
        'HTTP_SEC_WEBSOCKET_EXTENSIONS': 'permessage-deflate; client_max_window_bits', 
        'wsgi.input': <gevent.pywsgi.Input object at 0x03A9DCA8>, 
        'wsgi.input_terminated': True, 'wsgi.websocket_version': '13', 
        
        'wsgi.websocket': <geventwebsocket.websocket.WebSocket object at 0x03A9DC00>, 
        
        'werkzeug.request': <Request 'http://192.168.16.14:8888/websocket' [GET]>
        }
    '''
    websocket-environ

    websocket-headers:     Upgrade: websocket   #websocket请求中的标识

    '''
        Host: 192.168.16.14:8888
        Connection: Upgrade
        Pragma: no-cache
        Cache-Control: no-cache
        User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36
        
        Upgrade: websocket   #websocket请求中的标识
        
        Origin: http://192.168.16.14:8888
        Sec-Websocket-Version: 13
        Accept-Encoding: gzip, deflate
        Accept-Language: zh-CN,zh;q=0.9
        Sec-Websocket-Key: Oyfq0MCEBnsypKstjjRvYg==
        Sec-Websocket-Extensions: permessage-deflate; client_max_window_bits
    '''
    websocket-headers

    (1)基于websocket+flask实现的群聊无昵称即时通信

      flask_websocket(MUC_Nonick).py  

     1 '''
     2 基于websocket+flask实现的群聊无昵称即时通信
     3 设计列表client_list = []来存储客户端与服务器的连接,
     4 服务收到任意客户端的信息(信息时),对连接存储列表进行遍历获取每个连接,直接进行转发
     5 '''
     6 from flask import Flask, render_template, request
     7 
     8 # pip install gevent-websocket导入IO多路复用模块
     9 from geventwebsocket.handler import WebSocketHandler  # 提供WS(websocket)协议处理
    10 from geventwebsocket.server import WSGIServer  # websocket服务承载
    11 # WSGIServer导入的就是gevent.pywsgi中的类
    12 # from gevent.pywsgi import WSGIServer
    13 from geventwebsocket.websocket import WebSocket  # websocket语法提示
    14 
    15 app = Flask(__name__)
    16 
    17 # @app.route('/websocket')
    18 # 多个客户端可以同时给falsk服务端发送ws协议的信息
    19 # def websocket():
    20 #     client_socket=request.environ.get('wsgi.websocket') #type:WebSocket
    21 #     while 1:
    22 #             msg_from_cli=client_socket.receive()
    23 #             print(msg_from_cli)
    24 # 多个客户端可以同时给falsk服务端发送ws协议的信息,同时服务端将信息转送到每个客户端页面,实现多人聊天室即时通信
    25 client_list = []
    26 
    27 
    28 @app.route('/websocket')
    29 def websocket():
    30     client_socket = request.environ.get('wsgi.websocket')  # type:WebSocket
    31     client_list.append(client_socket)
    32     # print(len(client_list), client_list)
    33     while 1:
    34         msg_from_cli = client_socket.receive()
    35         # print(msg_from_cli)
    36         #收到任何一个客户端的信息都进行全部转发(注意如果某个客户端连接断开,在遍历发送时连接不存在会报错,需要异常处理)
    37         for client in client_list:
    38             try:
    39                 client.send(msg_from_cli)
    40             except Exception as e:
    41                 continue
    42 
    43 @app.route('/chat')
    44 def chat():
    45     return render_template('MUC_Nonick.html')
    46 
    47 
    48 if __name__ == '__main__':
    49     # app.run('192.168.16.14',8888,debug=True)
    50     http_server = WSGIServer(('192.168.16.14', 8888), application=app, handler_class=WebSocketHandler)
    51     http_server.serve_forever()
    flask_websocket(MUC_Nonick).py

      MUC_Nonick.html  

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>多用户聊天无昵称</title>
     6 </head>
     7 <body>
     8 <div id="chat_room">
     9     <p>请输入聊天内容:<input type="text" id="msg">
    10         <button id="send" onclick="send()">发送</button>
    11     </p>
    12     <div id="chat_content"></div>
    13 </div>
    14 </body>
    15 <script type="application/javascript">
    16     var ws = new WebSocket('ws://192.168.16.14:8888/websocket');
    17     ws.onmessage = function (MessageEvent) {
    18         //console.log(MessageEvent);
    19        //console.log(MessageEvent.data);
    20         var time=new Date();
    21         var t= time.toLocaleString();
    22         var p=document.createElement("p");
    23         p.innerText="("+t+")"+MessageEvent.data;
    24         document.getElementById('chat_content').appendChild(p);
    25     };
    26 
    27     function send() {
    28         var msg = document.getElementById('msg').value;
    29         ws.send(msg);
    30     }
    31 </script>
    32 </html>
    MUC_Nonick.html

    (2)基于websocket+flask实现的群聊有昵称即时通信

      版本一:通过动态路有参数获取客户端昵称

      flask_websocket(MUC_nick_route).py  

     1 '''
     2 基于websocket+flask实现的群聊即时通信
     3 设计字典client_dict = {}来存储{客户端的名字:客户端与服务器的连接},客户端的名字通过动态路由参数获取到,
     4 服务器接收客户端发来的信息(经过json序列化后的字典),对存储连接信息的字典进行遍历,获取客户端的连接,直接转发
     5 '''
     6 from flask import Flask, render_template, request
     7 from geventwebsocket.handler import WebSocketHandler  # 提供WS(websocket)协议处理
     8 from geventwebsocket.server import WSGIServer  # websocket服务承载
     9 from geventwebsocket.websocket import WebSocket  # websocket语法提示
    10 
    11 app = Flask(__name__)
    12 
    13 client_dict = {}
    14 
    15 
    16 @app.route('/websocket/<client_name>')#通过动态路由参数获取昵称,必须在视图函定义同名形参接收
    17 def websocket(client_name):
    18     client_socket = request.environ.get('wsgi.websocket')  # type:WebSocket
    19     client_dict[client_name] = client_socket
    20     # print(len(client_dict), client_dict)
    21     while 1:
    22         msg_from_cli = client_socket.receive()
    23         for client in client_dict.values():
    24             try:
    25                 client.send(msg_from_cli)
    26             except Exception as e:
    27                 continue
    28 
    29 
    30 @app.route('/chat')
    31 def chat():
    32     return render_template('MUC_nick_route.html')
    33 
    34 
    35 if __name__ == '__main__':
    36     # app.run('192.168.16.14',8888,debug=True)
    37     http_server = WSGIServer(('192.168.16.14', 8888), application=app, handler_class=WebSocketHandler)
    38     http_server.serve_forever()
    flask_websocket(MUC_nick_route).py

      MUC_nick_route.html

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>多用户聊天无昵称</title>
     6 </head>
     7 <body>
     8 <div id="chat_room">
     9     <p>输入昵称进入多人聊天室:<input type="text" id="client_name"></input>
    10         <button id='login' onclick="login()">登录</button>
    11     </p>
    12     <p id='chat_msg' hidden="hidden">请输入聊天内容:<input type="text" id="msg">
    13         <button id="send" onclick="send()">发送</button>
    14     </p>
    15     <div id="chat_content" hidden="hidden"></div>
    16 </div>
    17 </body>
    18 <script type="application/javascript">
    19     var ws = null;
    20     var name=null;
    21 
    22     function login() {
    23         document.getElementById('login').setAttribute('hidden', 'hidden');
    24         document.getElementById('client_name').setAttribute('disabled', 'disabled');
    25         document.getElementById('chat_msg').removeAttribute('hidden');
    26         document.getElementById('chat_content').removeAttribute('hidden');
    27         name = document.getElementById('client_name').value;
    28         //进行WS实例化
    29         ws = new WebSocket('ws://192.168.16.14:8888/websocket/' + name);
    30 
    31         //监听服务器发来的消息(json数据)
    32         ws.onmessage = function (MessageEvent) {
    33             //console.log(MessageEvent);
    34             //console.log(MessageEvent.data);
    35             var content_str = JSON.parse(MessageEvent.data);
    36             var time = new Date();
    37             var t = time.toLocaleTimeString();
    38             var p = document.createElement("p");
    39             p.innerText = content_str.name + "(" + t + "):" + content_str.msg;
    40             document.getElementById('chat_content').appendChild(p);
    41         };
    42     };
    43 
    44 
    45     //聊天信息发送(json数据)
    46     function send() {
    47         var msg = document.getElementById('msg').value;
    48         var data = {
    49             name: name,
    50             msg: msg,
    51         };
    52         var data_json = JSON.stringify(data);
    53         ws.send(data_json);
    54     }
    55 </script>
    56 </html>
    MUC_nick_route.html

     

      版本二:通过websocket接收客户端发来基于websocket发来的昵称: 

      flask_websocket(MUC_nick).py

     1 '''
     2 基于websocket+flask实现的群聊即时通信
     3 设计字典client_dict = {}来存储{客户端的名字:客户端与服务器的连接},客户端的名字通过客户端执行WS请求协议发送获取,
     4 服务器再持续接收客户端发来的信息(经过json序列化后的字典),对存储连接信息的字典进行遍历,获取客户端的连接,直接转发
     5 '''
     6 from flask import Flask, render_template, request
     7 from geventwebsocket.handler import WebSocketHandler  # 提供WS(websocket)协议处理
     8 from geventwebsocket.server import WSGIServer  # websocket服务承载
     9 from geventwebsocket.websocket import WebSocket  # websocket语法提示
    10 
    11 
    12 app = Flask(__name__)
    13 
    14 client_dict = {}
    15 
    16 
    17 @app.route('/websocket')
    18 def websocket():
    19     client_socket = request.environ.get('wsgi.websocket')  # type:WebSocket
    20     # print(client_socket)
    21     client_name = client_socket.receive()
    22     client_dict[client_name] = client_socket
    23     # print(len(client_dict), client_dict)
    24     while 1:
    25         msg_from_cli = client_socket.receive()
    26         # msg_from_cli_str=json.loads(msg_from_cli)
    27         # print(msg_from_cli_str)
    28         for client in client_dict.values():
    29             try:
    30                 client.send(msg_from_cli)
    31             except Exception as e:
    32                 continue
    33 
    34 
    35 @app.route('/chat')
    36 def chat():
    37     return render_template('MUC_nick.html')
    38 
    39 
    40 if __name__ == '__main__':
    41     # app.run('192.168.16.14',8888,debug=True)
    42     http_server = WSGIServer(('192.168.16.14', 8888), application=app, handler_class=WebSocketHandler)
    43     http_server.serve_forever()
    flask_websocket(MUC_nick).py

      MUC_nick.html  

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>多用户聊天无昵称</title>
     6 </head>
     7 <body>
     8 <div id="chat_room">
     9     <p>输入昵称进入多人聊天室:<input type="text" id="client_name"></input>
    10         <button id='login' onclick="login()">登录</button>
    11     </p>
    12     <p id='chat_msg' hidden="hidden">请输入聊天内容:<input type="text" id="msg">
    13         <button id="send" onclick="send()">发送</button>
    14     </p>
    15     <div id="chat_content" ></div>
    16 </div>
    17 </body>
    18 <script type="application/javascript">
    19     var ws = new WebSocket('ws://192.168.16.14:8888/websocket');
    20     var name = null;
    21 
    22     //向服务端发送本机昵称
    23     function login() {
    24         document.getElementById('login').setAttribute('hidden', 'hidden');
    25         document.getElementById('client_name').setAttribute('disabled', 'disabled');
    26         document.getElementById('chat_msg').removeAttribute('hidden');
    27         document.getElementById('chat_content').removeAttribute('hidden');
    28         name = document.getElementById('client_name').value;
    29         ws.send(name);
    30     };
    31 
    32 
    33    //监听服务器发来的消息(json数据)
    34     ws.onmessage = function (MessageEvent) {
    35         //console.log(MessageEvent);
    36         //console.log(MessageEvent.data);
    37         var content_str = JSON.parse(MessageEvent.data);
    38         var time = new Date();
    39         var t = time.toLocaleTimeString();
    40         var p = document.createElement("p");
    41         p.innerText = content_str.name + "(" + t + "):" + content_str.msg;
    42         document.getElementById('chat_content').appendChild(p);
    43     };
    44 
    45 
    46     //聊天信息发送(json数据)
    47     function send() {
    48         var msg = document.getElementById('msg').value;
    49         var data = {
    50             name: name,
    51             msg: msg
    52         };
    53         var data_json = JSON.stringify(data);
    54         ws.send(data_json);
    55     }
    56 </script>
    57 </html>
    MUC_nick.html

    (3)基于websocket+flask实现的私聊即时通信

      flask_websocket(Private_chat).py

     1 '''
     2 基于websocket+flask实现的私聊即时通信
     3 设计字典client_dict = {}来存储{客户端的名字:客户端与服务器的连接},客户端的名字通过动态路由参数获取到,
     4 服务器通过客户端发来的信息(经过json序列化后的字典)中的目标客户端名字,在存储字典中获取目标客户端的连接,直接转发
     5 '''
     6 from flask import Flask, render_template, request
     7 from geventwebsocket.handler import WebSocketHandler  # 提供WS(websocket)协议处理
     8 from geventwebsocket.server import WSGIServer  # websocket服务承载
     9 from geventwebsocket.websocket import WebSocket  # websocket语法提示
    10 import json
    11 
    12 app = Flask(__name__)
    13 
    14 client_dict = {}
    15 
    16 
    17 @app.route('/websocket/<client_name>')  # 通过动态路由参数获取昵称,必须在视图函定义同名形参接收
    18 def websocket(client_name):
    19     client_socket = request.environ.get('wsgi.websocket')  # type:WebSocket
    20     client_dict[client_name] = client_socket
    21     if client_socket:
    22         while 1:
    23             msg_from_cli = client_socket.receive()
    24             to_client = json.loads(msg_from_cli).get('to_client')
    25             client = client_dict.get(to_client)
    26             try:
    27                 client.send(msg_from_cli)
    28             except Exception as e:
    29                 continue
    30 
    31 
    32 @app.route('/chat')
    33 def chat():
    34     return render_template('Private_chat.html')
    35 
    36 
    37 if __name__ == '__main__':
    38     http_server = WSGIServer(('192.168.16.14', 8888), application=app, handler_class=WebSocketHandler)
    39     http_server.serve_forever()
    flask_websocket(Private_chat).py

      Private_chat.html  

     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>单人聊天室</title>
     6 
     7 </head>
     8 <body>
     9 <div id="chat_room">
    10     <p>输入昵称进入单人聊天室:<input type="text" id="client_name"></input>
    11         <button id='login' onclick="login()">登录</button>
    12     </p>
    13     <p hidden id="client_recv">收信人:<input type="text" id="to_client"></p>
    14     <p id='chat_msg' hidden="hidden">请输入聊天内容:<input type="text" id="msg">
    15 
    16         <button id="send" onclick="send()">发送</button>
    17     </p>
    18     <div id="chat_content" hidden="hidden"></div>
    19 </div>
    20 </body>
    21 <script type="application/javascript">
    22     var ws = null;
    23     var name=null;
    24 
    25     function login() {
    26         document.getElementById('login').setAttribute('hidden', 'hidden');
    27         document.getElementById('client_name').setAttribute('disabled', 'disabled');
    28         document.getElementById('chat_msg').removeAttribute('hidden');
    29         document.getElementById('chat_content').removeAttribute('hidden');
    30         document.getElementById('client_recv').removeAttribute('hidden');
    31 
    32         name = document.getElementById('client_name').value;
    33         //进行WS实例化
    34         ws = new WebSocket('ws://192.168.16.14:8888/websocket/' + name);
    35 
    36         //监听服务器发来的消息(json数据)
    37         ws.onmessage = function (MessageEvent) {
    38             //console.log(MessageEvent);
    39             //console.log(MessageEvent.data);
    40             var content_str = JSON.parse(MessageEvent.data);
    41             var time = new Date();
    42             var t = time.toLocaleTimeString();
    43             var p = document.createElement("p");
    44             p.innerText = content_str.name + "(" + t + "):" + content_str.msg;
    45             document.getElementById('chat_content').appendChild(p);
    46         };
    47     };
    48 
    49 
    50     //聊天信息发送(json数据)
    51     function send() {
    52         var msg = document.getElementById('msg').value;
    53         var to_client=document.getElementById('to_client').value;
    54         var data = {
    55             name: name,
    56             msg: msg,
    57             to_client:to_client
    58         };
    59 
    60         var data_json = JSON.stringify(data);
    61         ws.send(data_json);
    62 
    63 
    64         var time = new Date();
    65             var t = time.toLocaleTimeString();
    66             var p = document.createElement("p");
    67             p.innerText = name + "(" + t + "):" + msg;
    68             document.getElementById('chat_content').appendChild(p);
    69 
    70 
    71 
    72 
    73 
    74     }
    75 </script>
    76 </html>
    Private_chat.html
  • 相关阅读:
    Codeforces 934 B.A Prosperous Lot
    Codeforces 934 A.Compatible Pair
    UVA 12898
    Codeforces Round #376 (Div. 2) C. Socks bfs
    Codeforces Round #377 (Div. 2) C. Sanatorium 水题
    Codeforces Round #377 (Div. 2) D. Exams 二分
    Codeforces Beta Round #91 (Div. 1 Only) E. Lucky Array 分块
    hdu 5154 Harry and Magical Computer 拓扑排序
    Codeforces Round #272 (Div. 2) C. Dreamoon and Sums 数学
    Codeforces Round #288 (Div. 2) C. Anya and Ghosts 模拟
  • 原文地址:https://www.cnblogs.com/open-yang/p/11191712.html
Copyright © 2011-2022 走看看