生活随笔
收集整理的這篇文章主要介紹了
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更加豐富的管理員功能
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
try:s
= socket
.socket
(socket
.AF_INET
, socket
.SOCK_DGRAM
)s
.connect
(('8.8.8.8', 80))IP
= s
.getsockname
()[0]
finally:s
.close
()
USERS
= {}
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"] = name
if len(USERS
) != 0: message
= json
.dumps
({"type": "user", "content": data
["content"], "from": name
})elif data
["type"] == 'login':USERS
[data
["content"]] = websocket
if len(USERS
) != 0: message
= json
.dumps
({"type": "login", "content": data
["content"], "user_list": list(USERS
.keys
())})elif data
["type"] == 'logout':del USERS
[data
["content"]]if len(USERS
) != 0: message
= 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的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。