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相关推荐
- Python实现网络聊天室(支持多人聊天与私聊)
实验名称: 网络聊天室 功能: i. 掌握利用Socket进行编程的技术 ii. 掌握多线程技术,保证双方可以同时发送 iii. 建立聊天工具 iv. 可以和单人聊天 v. 可以和多个人同时进行聊天 ...
- python socket 网络聊天室_Python基于Socket实现简单聊天室
本文实例为大家分享了Python基于Socket实现简单聊天室,供大家参考,具体内容如下 服务端 #!/usr/bin/env python # -*- coding: utf-8 -*- # @Ti ...
- python基于udp的网络聊天室再用tkinter显示_Python实现网络聊天室的示例代码(支持多人聊天与私聊)...
实验名称: 网络聊天室 功能: i. 掌握利用Socket进行编程的技术 ii. 掌握多线程技术,保证双方可以同时发送 iii. 建立聊天工具 iv. 可以和单人聊天 v. 可以和多个人同时进行聊天 ...
- Python实现网络聊天
Python实现网络聊天室(支持多人聊天与私聊) 实验名称: 功能: 概述 代码解释 实验名称: 网络聊天室 功能: i. 掌握利用Socket进行编程的技术 ii. 掌握多线程技术,保证双方可以同时 ...
- [NUAA]Python用UDP协议建立带有私聊功能的网络聊天室-建立聊天工具
文章目录 前言 1.网络聊天室的基本架构是什么? 1.1 客户端和服务器的架构 1.2 通信协议的选择以及多线程通信 1.2.1 多线程通信 1.2.2 通信协议选择 1.3 前后端功能设计思路 1. ...
- 【python】实现多人网络聊天室
利用socket套接字实现多台计算机之间的连接 server: import socket #socket 是一种套接字,用来描述IP和port import os import threading ...
- 视频教程-多人网络聊天室-Unity3D
多人网络聊天室 广州市码锋网络有限责任公司创始人,从事游戏开发九年,熟练前后端的各种技术,我很乐意将企业中商用的技术分享给你,帮助你解决工作的各种问题. 官剑铭 ¥39.00 立即订阅 扫码下载「CS ...
- 网络聊天室_TCP服务端
初学Python记录点滴生活_1 ps:正经人谁写日记? 网络聊天室_TCP服务端 具体实现步骤 1.编写一个TCP服务端程序,循环等待接受客户端的连接请求 2.当客户端和服务端建立连接成功,创建子线 ...
- 基于python实现的聊天室(服务端)
前言 就是自己想用python做一个聊天室,然后看看socket库,websocket库,有点底层,然后也会用到协程的东西,不是很明白,一时间也不知道怎么写,然后就用了封装好的python-socke ...
- 视频教程-网络聊天室Java基础版(Socket_Swing编程)仿QQ聊天-Java
网络聊天室Java基础版(Socket_Swing编程)仿QQ聊天 IT行业资深从业者,7年资深Java高级开发,Java架构师.曾就职银行.电信等行业多家上市公司.担任项目负责人,软件架构师.有丰富 ...
最新文章
- arm linux内核调试,kgdb在ARM开发板上调试kernel成功
- Java自动装箱与拆箱
- 从单片机转到嵌入式Linux的跨度大吗?
- 数据库mysql的注释怎么加_mysql表如何添加字段注释
- 【.Net Framework 体积大?】不安装.net framework 也能运行!?原理补充-3
- 真无线蓝牙耳机哪个好?四款买了不亏的真无线蓝牙耳机
- ipmitool 工具的使用姿势
- 惠普总裁口述的职业规划(3)
- VIJOS-P1626 桐桐的糖果计划
- SpringBoot(二): 使用Dokcer+SpringCloud+Consul+Fabio搭建微服务
- 有关H5第七章的盒子模型介绍
- 数据库系统概论复习提纲
- mysql 实例和数据库名_oracle 实例名和服务名以及数据库名区别
- 前端 查看页面在不同分辨率下效果
- 内存缓存(in-memory cache)
- gsoc 任务_黑客#GSOC:如何获得现实生活经验并支持开源
- Google Play开发者账号被封、下架、提审被拒原因分析
- ESP32学习--库添加
- excel的FILTERXML函数
- Ubuntu基础笔记(幕布)
热门文章
- 百度搜索升级冰桶算法5.0
- Beyond Compare 提示“缺少评估信息或损坏”
- 【直播预告】相机模型与标定——Real world超级公开课
- 计网考点 无线局域网
- jeecms 取附件
- oracle primavera p6 破解版,P6项目管理软件下载 Primavera P6 Professional(项目管理软件) 16.1 免费安装版(附安装教程) 下载-脚本之家...
- Python基础---List(列表)
- 量化策略“高股息率模型”长期有效性的实证
- ubuntu两个显示器只出一个_Ubuntu设置笔记本电脑双显示器(linux)
- 思科ccie认证网络工程师——MAC地址认证和MAC地址旁路认证解析必看