日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python websockets 网络聊天室V1

發布時間:2023/12/18 python 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python websockets 网络聊天室V1 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
  • 效果:

    python websockets 網絡聊天室V1

程序打包鏈接:https://pan.baidu.com/s/1L0Cwur-VnD-BLjkf5n1K1w
提取碼:gsqt

  • 新增
  • 將程序打包成exe文件
  • 可以在同一網絡下通信,不用像v0一樣傻傻的在同一臺電腦自娛自樂。(若想放在服務器上,請配置好flask的生產環境,否則據說會有漏洞)
  • 聊天記錄保存在chat.log里
  • 注:由于編程能力有限,退出務必是按ctrl+c,直接關閉窗口會生成孤兒進程

    • 我都寫了啥
  • py里有p_web 和 p_chat_server 兩個進程,分別負責處理HTML的路由和聊天的后端
  • 主要看html 里的ws.onmessage 和 py里的async def chat(websocket, path) 函數。他們以json方式進行信息交互
    • 下次迭代
  • 更加好看的UI
  • 更加豐富的管理員功能
    • 代碼:
    # -*- coding:utf8 -*-import json import socket import asyncio import logging import websockets import multiprocessing from multiprocessing import Process from flask import Flask, render_template, requestIP = '127.0.0.1' PORT_WEB = 800 PORT_CHAT = 1234# 此方法利用UDP協議,生成一個UDP包,將自己的IP放入UDP協議頭中,然后再從中獲取本機的IP。此方法雖然不會真實向外發包,但仍然會申請一個UDP的端口 try:s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)s.connect(('8.8.8.8', 80))IP = s.getsockname()[0] finally:s.close()# 保存字典 名字:websockets USERS = {}#提供html app = Flask(__name__) @app.route('/') def index_chat():return render_template("index.html", ip=IP, port=PORT_CHAT) def web():app.run(host='0.0.0.0', port=PORT_WEB)#提供聊天的后臺 async def chat(websocket, path):logging.basicConfig(format='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s',filename="chat.log",level=logging.INFO)# 握手await websocket.send(json.dumps({"type": "handshake"}))async for message in websocket:data = json.loads(message)message = ''# 用戶發信息if data["type"] == 'send':name = '404'for k, v in USERS.items():if v == websocket:name = kdata["from"] = nameif 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())})#打印聊天信息到日志logging.info(data)# 群發await asyncio.wait([user.send(message) for user in USERS.values()])def chat_server():start_server = websockets.serve(chat, '0.0.0.0', PORT_CHAT)asyncio.get_event_loop().run_until_complete(start_server)asyncio.get_event_loop().run_forever()if __name__ == "__main__":multiprocessing.freeze_support()p_web = Process(target=web, daemon = True)p_web.start()p_chat_server = Process(target=chat_server, daemon = True)p_chat_server.start()print("按下ctrl + c 結束程序。聊天記錄將保存在chat.log")print("聊天室地址" + IP + ':' + str(PORT_WEB))p_web.join()p_chat_server.terminate() <!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 id='ipp' ip={{ip}} port={{port}}></div><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 url = "ws://" + document.getElementById("ipp").getAttribute("ip") + ':' + document.getElementById("ipp").getAttribute("port");console.log(url);var ws = new WebSocket(url);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>

    總結

    以上是生活随笔為你收集整理的python websockets 网络聊天室V1的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。