当前位置: 代码迷 >> 综合 >> python websockets 网络聊天室V0
  详细解决方案

python websockets 网络聊天室V0

热度:80   发布时间:2023-09-22 20:02:44.0
  • 实现效果

python websockets 网络聊天室V0

  • 使用方式
  1. 将前后端分别保存为html和py文件。

  2. pip install asyncio、json、websockets

  3. 双击打开html

*在一台电脑开两个网页的确有点傻,您可以修改代码ip,再将py文件在电脑运行。可达到局域网通信(参见 v1版本)

  • 后端
#!/usr/bin/env python
# 后端
# WS server example that synchronizes state across clientsimport asyncio
import json
import websockets# 名字:websockets
USERS = {
    }
async def chat(websocket, path):# 握手await websocket.send(json.dumps({
    "type": "handshake"}))async for message in websocket:data = json.loads(message)print(data)message = ''# 用户发信息if data["type"] == 'send':name = '404'for k, v in USERS.items():if v == websocket:name = kif len(USERS) != 0:  # asyncio.wait doesn't accept an empty listmessage = json.dumps({
    "type": "user", "content": data["content"], "from": name})#用户登录elif data["type"] == 'login':USERS[data["content"]] = websocketif len(USERS) != 0:  # asyncio.wait doesn't accept an empty listmessage = json.dumps({
    "type": "login", "content": data["content"], "user_list": list(USERS.keys())})#用户退出elif data["type"] == 'logout':del USERS[data["content"]]if len(USERS) != 0:  # asyncio.wait doesn't accept an empty listmessage = json.dumps({
    "type": "logout", "content": data["content"], "user_list": list(USERS.keys())})# 群发await asyncio.wait([user.send(message) for user in USERS.values()])start_server = websockets.serve(chat, "127.0.0.1", 1234)asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
  • 前端
<!DOCTYPE html>
<html><head><title></title><meta http-equiv="content-type" content="text/html;charset=utf-8"><style>p {
    text-align: left;padding-left: 20px;}</style>
</head><body><div style="width: 800px;height: 600px;margin: 30px auto;text-align: center"><h1>websocket聊天室</h1><div style="width: 800px;border: 1px solid gray;height: 300px;"><div style="width: 200px;height: 300px;float: left;text-align: left;"><p><span>当前在线:</span><span id="user_num">0</span></p><div id="user_list" style="overflow: auto;"></div></div><div id="msg_list" style="width: 598px;border: 1px solid gray; height: 300px;overflow: scroll;float: left;"></div></div><br><textarea id="msg_box" rows="6" cols="50" onkeydown="confirm(event)"></textarea><br><input type="button" value="发送" onclick="send()"></div>
</body></html><script type="text/javascript">// 存储用户名到全局变量,握手成功后发送给服务器var uname = prompt('请输入用户名', 'user' + uuid(8, 16));var ws = new WebSocket("ws://127.0.0.1:1234");ws.onopen = function() {
    var data = "系统消息:建立连接成功";listMsg(data);};/*** 分析服务器返回信息** msg.type : user 普通信息;system 系统信息;handshake 握手信息;login 登陆信息; logout 退出信息;* msg.from : 消息来源* msg.content: 消息内容*/ws.onmessage = function(e) {
    var msg = JSON.parse(e.data);var sender, user_name, name_list, change_type;switch (msg.type) {
    case 'system':sender = '系统消息: ';break;case 'user':sender = msg.from + ': ';break;case 'handshake':var user_info = {
    'type': 'login','content': uname};sendMsg(user_info);return;case 'login':case 'logout':user_name = msg.content;name_list = msg.user_list;change_type = msg.type;dealUser(user_name, change_type, name_list);return;}var data = sender + msg.content;listMsg(data);};ws.onerror = function() {
    var data = "系统消息 : 出错了,请退出重试.";listMsg(data);};//窗口关闭时,发信息给服务器,说明下线了window.onbeforeunload = function() {
      var user_info = {
    'type': 'logout','content': uname};sendMsg(user_info);ws.close();}/*** 在输入框内按下回车键时发送消息** @param event** @returns {
    boolean}*/function confirm(event) {
    var key_num = event.keyCode;if (13 == key_num) {
    send();} else {
    return false;}}/*** 发送并清空消息输入框内的消息*/function send() {
    var msg_box = document.getElementById("msg_box");var content = msg_box.value;var reg = new RegExp("\r\n", "g");content = content.replace(reg, "");var msg = {
    'content': content.trim(),'type': 'send'};sendMsg(msg);msg_box.value = '';// todo 清除换行符}/*** 将消息内容添加到输出框中,并将滚动条滚动到最下方*/function listMsg(data) {
    var msg_list = document.getElementById("msg_list");var msg = document.createElement("p");msg.innerHTML = data;msg_list.appendChild(msg);msg_list.scrollTop = msg_list.scrollHeight;}/*** 处理用户登陆消息** @param user_name 用户名* @param type  login/logout* @param name_list 用户列表*/function dealUser(user_name, type, name_list) {
    var user_list = document.getElementById("user_list");var user_num = document.getElementById("user_num");while (user_list.hasChildNodes()) {
    user_list.removeChild(user_list.firstChild);}for (var index in name_list) {
    var user = document.createElement("p");user.innerHTML = name_list[index];user_list.appendChild(user);}user_num.innerHTML = name_list.length;user_list.scrollTop = user_list.scrollHeight;var change = type == 'login' ? '上线' : '下线';var data = '系统消息: ' + user_name + ' 已' + change;listMsg(data);}/*** 将数据转为json并发送* @param msg*/function sendMsg(msg) {
    var data = JSON.stringify(msg);ws.send(data);}/*** 生产一个全局唯一ID作为用户名的默认值;** @param len* @param radix* @returns {
    string}*/function uuid(len, radix) {
    var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');var uuid = [],i;radix = radix || chars.length;if (len) {
    for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];} else {
    var r;uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';uuid[14] = '4';for (i = 0; i < 36; i++) {
    if (!uuid[i]) {
    r = 0 | Math.random() * 16;uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];}}}return uuid.join('');}
</script>

前端代码拷贝自这位大佬。在前端增加关闭窗口发信息给后台的函数。

https://github.com/zhenbianshu/websocket