• 效果:

    python websockets 网络聊天室V1

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

  • 新增
  1. 将程序打包成exe文件
  2. 可以在同一网络下通信,不用像v0一样傻傻的在同一台电脑自娱自乐。(若想放在服务器上,请配置好flask的生产环境,否则据说会有漏洞)
  3. 聊天记录保存在chat.log里

注:由于编程能力有限,退出务必是按ctrl+c,直接关闭窗口会生成孤儿进程

  • 我都写了啥
  1. py里有p_web 和 p_chat_server 两个进程,分别负责处理HTML的路由和聊天的后端
  2. 主要看html 里的ws.onmessage 和 py里的async def chat(websocket, path) 函数。他们以json方式进行信息交互
  • 下次迭代
  1. 更加好看的UI
  2. 更加丰富的管理员功能
  • 代码:
# -*- 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相关推荐

  1. Python实现网络聊天室(支持多人聊天与私聊)

    实验名称: 网络聊天室 功能: i. 掌握利用Socket进行编程的技术 ii. 掌握多线程技术,保证双方可以同时发送 iii. 建立聊天工具 iv. 可以和单人聊天 v. 可以和多个人同时进行聊天 ...

  2. python socket 网络聊天室_Python基于Socket实现简单聊天室

    本文实例为大家分享了Python基于Socket实现简单聊天室,供大家参考,具体内容如下 服务端 #!/usr/bin/env python # -*- coding: utf-8 -*- # @Ti ...

  3. python基于udp的网络聊天室再用tkinter显示_Python实现网络聊天室的示例代码(支持多人聊天与私聊)...

    实验名称: 网络聊天室 功能: i. 掌握利用Socket进行编程的技术 ii. 掌握多线程技术,保证双方可以同时发送 iii. 建立聊天工具 iv. 可以和单人聊天 v. 可以和多个人同时进行聊天 ...

  4. Python实现网络聊天

    Python实现网络聊天室(支持多人聊天与私聊) 实验名称: 功能: 概述 代码解释 实验名称: 网络聊天室 功能: i. 掌握利用Socket进行编程的技术 ii. 掌握多线程技术,保证双方可以同时 ...

  5. [NUAA]Python用UDP协议建立带有私聊功能的网络聊天室-建立聊天工具

    文章目录 前言 1.网络聊天室的基本架构是什么? 1.1 客户端和服务器的架构 1.2 通信协议的选择以及多线程通信 1.2.1 多线程通信 1.2.2 通信协议选择 1.3 前后端功能设计思路 1. ...

  6. 【python】实现多人网络聊天室

    利用socket套接字实现多台计算机之间的连接 server: import socket #socket 是一种套接字,用来描述IP和port import os import threading ...

  7. 视频教程-多人网络聊天室-Unity3D

    多人网络聊天室 广州市码锋网络有限责任公司创始人,从事游戏开发九年,熟练前后端的各种技术,我很乐意将企业中商用的技术分享给你,帮助你解决工作的各种问题. 官剑铭 ¥39.00 立即订阅 扫码下载「CS ...

  8. 网络聊天室_TCP服务端

    初学Python记录点滴生活_1 ps:正经人谁写日记? 网络聊天室_TCP服务端 具体实现步骤 1.编写一个TCP服务端程序,循环等待接受客户端的连接请求 2.当客户端和服务端建立连接成功,创建子线 ...

  9. 基于python实现的聊天室(服务端)

    前言 就是自己想用python做一个聊天室,然后看看socket库,websocket库,有点底层,然后也会用到协程的东西,不是很明白,一时间也不知道怎么写,然后就用了封装好的python-socke ...

  10. 视频教程-网络聊天室Java基础版(Socket_Swing编程)仿QQ聊天-Java

    网络聊天室Java基础版(Socket_Swing编程)仿QQ聊天 IT行业资深从业者,7年资深Java高级开发,Java架构师.曾就职银行.电信等行业多家上市公司.担任项目负责人,软件架构师.有丰富 ...

最新文章

  1. arm linux内核调试,kgdb在ARM开发板上调试kernel成功
  2. Java自动装箱与拆箱
  3. 从单片机转到嵌入式Linux的跨度大吗?
  4. 数据库mysql的注释怎么加_mysql表如何添加字段注释
  5. 【.Net Framework 体积大?】不安装.net framework 也能运行!?原理补充-3
  6. 真无线蓝牙耳机哪个好?四款买了不亏的真无线蓝牙耳机
  7. ipmitool 工具的使用姿势
  8. 惠普总裁口述的职业规划(3)
  9. VIJOS-P1626 桐桐的糖果计划
  10. SpringBoot(二): 使用Dokcer+SpringCloud+Consul+Fabio搭建微服务
  11. 有关H5第七章的盒子模型介绍
  12. 数据库系统概论复习提纲
  13. mysql 实例和数据库名_oracle 实例名和服务名以及数据库名区别
  14. 前端 查看页面在不同分辨率下效果
  15. 内存缓存(in-memory cache)
  16. gsoc 任务_黑客#GSOC:如何获得现实生活经验并支持开源
  17. Google Play开发者账号被封、下架、提审被拒原因分析
  18. ESP32学习--库添加
  19. excel的FILTERXML函数
  20. Ubuntu基础笔记(幕布)

热门文章

  1. 百度搜索升级冰桶算法5.0
  2. Beyond Compare 提示“缺少评估信息或损坏”
  3. 【直播预告】相机模型与标定——Real world超级公开课
  4. 计网考点 无线局域网
  5. jeecms 取附件
  6. oracle primavera p6 破解版,P6项目管理软件下载 Primavera P6 Professional(项目管理软件) 16.1 免费安装版(附安装教程) 下载-脚本之家...
  7. Python基础---List(列表)
  8. 量化策略“高股息率模型”长期有效性的实证
  9. ubuntu两个显示器只出一个_Ubuntu设置笔记本电脑双显示器(linux)
  10. 思科ccie认证网络工程师——MAC地址认证和MAC地址旁路认证解析必看