使用Python怎么實(shí)現(xiàn)一個(gè)網(wǎng)絡(luò)聊天室功能?針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡(jiǎn)單易行的方法。
創(chuàng)新互聯(lián)主營(yíng)定南網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營(yíng)網(wǎng)站建設(shè)方案,成都APP應(yīng)用開發(fā),定南h5成都微信小程序搭建,定南網(wǎng)站營(yíng)銷推廣歡迎定南等地區(qū)企業(yè)咨詢i. 掌握利用Socket進(jìn)行編程的技術(shù)
ii. 掌握多線程技術(shù),保證雙方可以同時(shí)發(fā)送
iii. 建立聊天工具
iv. 可以和單人聊天
v. 可以和多個(gè)人同時(shí)進(jìn)行聊天
vi. 使用圖形界面,顯示雙方的語(yǔ)錄
vii. 程序可以在一定程度上進(jìn)行錯(cuò)誤識(shí)別
實(shí)驗(yàn)通過聊天室可以完成單人或多人之間的聊天通信,功能的實(shí)現(xiàn)主要是通過Socket通信來(lái)實(shí)現(xiàn)。本次實(shí)驗(yàn)采用客戶端/服務(wù)器(C/S)架構(gòu)模式,通過Python語(yǔ)言來(lái)編寫服務(wù)器端與客戶端的程序。運(yùn)用多線程可完成多點(diǎn)對(duì)多點(diǎn)的聊天。
服務(wù)器端程序主要用于接收用戶信息,消息接收與轉(zhuǎn)發(fā)。
客戶端程序?qū)崿F(xiàn)用戶注冊(cè)登錄,聊天信息顯示與信息輸入。
統(tǒng)計(jì)當(dāng)前在線人數(shù),并且將新用戶加到用戶列表中。
Serve.py

這是服務(wù)器對(duì)于聊天服務(wù)的實(shí)現(xiàn)。

通過繼承threading.Thread類而實(shí)現(xiàn)多線程,重寫run函數(shù)。

接受來(lái)自客戶端的用戶名,如果用戶名為空,使用用戶的IP與端口作為用戶名。如果用戶名出現(xiàn)重復(fù),則在出現(xiàn)的用戶名依此加上后綴“2”、“3”、“4”……

在獲取用戶名后便會(huì)不斷地接受用戶端發(fā)來(lái)的消息(即聊天內(nèi)容),結(jié)束后關(guān)閉連接。

如果用戶斷開連接,將該用戶從用戶列表中刪除,然后更新用戶列表。

將地址與數(shù)據(jù)(需發(fā)送給客戶端)存入messages隊(duì)列。

服務(wù)端在接受到數(shù)據(jù)后,會(huì)對(duì)其進(jìn)行一些處理然后發(fā)送給客戶端,如下圖,對(duì)于聊天內(nèi)容,服務(wù)端直接發(fā)送給客戶端,而對(duì)于用戶列表,便由json.dumps處理后發(fā)送。

Client.py
建立連接,發(fā)送用戶名及判斷是否為私聊消息,私聊用~識(shí)別

接受來(lái)自服務(wù)器發(fā)送的消息

對(duì)接收到的消息進(jìn)行判斷,如果是在線用戶列表(用json.dumps處理過),便清空在線用戶列表框,并將此列表輸出在在線用戶列表框中。

如果是聊天內(nèi)容,便將其輸出在聊天內(nèi)容顯示框中。

設(shè)置登錄窗口

設(shè)置消息界面

設(shè)置在線用戶列表。

完整代碼:
Serve.py
import socket
import threading
import queue
import json # json.dumps(some)打包 json.loads(some)解包
import os
import os.path
import sys
IP = '127.0.0.1'
PORT = 9999 # 端口
messages = queue.Queue()
users = [] # 0:userName 1:connection
lock = threading.Lock()
def onlines(): # 統(tǒng)計(jì)當(dāng)前在線人員
online = []
for i in range(len(users)):
online.append(users[i][0])
return online
class ChatServer(threading.Thread):
global users, que, lock
def __init__(self): # 構(gòu)造函數(shù)
threading.Thread.__init__(self)
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
os.chdir(sys.path[0])
# 接受來(lái)自客戶端的用戶名,如果用戶名為空,使用用戶的IP與端口作為用戶名。如果用戶名出現(xiàn)重復(fù),則在出現(xiàn)的用戶名依此加上后綴“2”、“3”、“4”……
def receive(self, conn, addr): # 接收消息
user = conn.recv(1024) # 用戶名稱
user = user.decode()
if user == '用戶名不存在':
user = addr[0] + ':' + str(addr[1])
tag = 1
temp = user
for i in range(len(users)): # 檢驗(yàn)重名,則在重名用戶后加數(shù)字
if users[i][0] == user:
tag = tag + 1
user = temp + str(tag)
users.append((user, conn))
USERS = onlines()
self.Load(USERS,addr)
# 在獲取用戶名后便會(huì)不斷地接受用戶端發(fā)來(lái)的消息(即聊天內(nèi)容),結(jié)束后關(guān)閉連接。
try:
while True:
message = conn.recv(1024) # 發(fā)送消息
message = message.decode()
message = user + ':' + message
self.Load(message,addr)
conn.close()
# 如果用戶斷開連接,將該用戶從用戶列表中刪除,然后更新用戶列表。
except:
j = 0 # 用戶斷開連接
for man in users:
if man[0] == user:
users.pop(j) # 服務(wù)器段刪除退出的用戶
break
j = j+1
USERS = onlines()
self.Load(USERS,addr)
conn.close()
# 將地址與數(shù)據(jù)(需發(fā)送給客戶端)存入messages隊(duì)列。
def Load(self, data, addr):
lock.acquire()
try:
messages.put((addr, data))
finally:
lock.release()
# 服務(wù)端在接受到數(shù)據(jù)后,會(huì)對(duì)其進(jìn)行一些處理然后發(fā)送給客戶端,如下圖,對(duì)于聊天內(nèi)容,服務(wù)端直接發(fā)送給客戶端,而對(duì)于用戶列表,便由json.dumps處理后發(fā)送。
def sendData(self): # 發(fā)送數(shù)據(jù)
while True:
if not messages.empty():
message = messages.get()
if isinstance(message[1], str):
for i in range(len(users)):
data = ' ' + message[1]
users[i][1].send(data.encode())
print(data)
print('\n')
if isinstance(message[1], list):
data = json.dumps(message[1])
for i in range(len(users)):
try:
users[i][1].send(data.encode())
except:
pass
def run(self):
self.s.bind((IP,PORT))
self.s.listen(5)
q = threading.Thread(target=self.sendData)
q.start()
while True:
conn, addr = self.s.accept()
t = threading.Thread(target=self.receive, args=(conn, addr))
t.start()
self.s.close()
if __name__ == '__main__':
cserver = ChatServer()
cserver.start()Client.py
import socket
import tkinter
import tkinter.messagebox
import threading
import json
import tkinter.filedialog
from tkinter.scrolledtext import ScrolledText
IP = ''
PORT = ''
user = ''
listbox1 = '' # 用于顯示在線用戶的列表框
show = 1 # 用于判斷是開還是關(guān)閉列表框
users = [] # 在線用戶列表
chat = '------Group chat-------' # 聊天對(duì)象
#登陸窗口
root0 = tkinter.Tk()
root0.geometry("300x150")
root0.title('用戶登陸窗口')
root0.resizable(0,0)
one = tkinter.Label(root0,width=300,height=150,bg="LightBlue")
one.pack()
IP0 = tkinter.StringVar()
IP0.set('')
USER = tkinter.StringVar()
USER.set('')
labelIP = tkinter.Label(root0,text='IP地址',bg="LightBlue")
labelIP.place(x=20,y=20,width=100,height=40)
entryIP = tkinter.Entry(root0, width=60, textvariable=IP0)
entryIP.place(x=120,y=25,width=100,height=30)
labelUSER = tkinter.Label(root0,text='用戶名',bg="LightBlue")
labelUSER.place(x=20,y=70,width=100,height=40)
entryUSER = tkinter.Entry(root0, width=60, textvariable=USER)
entryUSER.place(x=120,y=75,width=100,height=30)
def Login(*args):
global IP, PORT, user
IP, PORT = entryIP.get().split(':')
user = entryUSER.get()
if not user:
tkinter.messagebox.showwarning('warning', message='用戶名為空!')
else:
root0.destroy()
loginButton = tkinter.Button(root0, text ="登錄", command = Login,bg="Yellow")
loginButton.place(x=135,y=110,width=40,height=25)
root0.bind('<Return>', Login)
root0.mainloop()
# 建立連接
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((IP, int(PORT)))
if user:
s.send(user.encode()) # 發(fā)送用戶名
else:
s.send('用戶名不存在'.encode())
user = IP + ':' + PORT
# 聊天窗口
root1 = tkinter.Tk()
root1.geometry("640x480")
root1.title('群聊')
root1.resizable(0,0)
# 消息界面
listbox = ScrolledText(root1)
listbox.place(x=5, y=0, width=640, height=320)
listbox.tag_config('tag1', foreground='red',backgroun="yellow")
listbox.insert(tkinter.END, '歡迎進(jìn)入群聊,大家開始聊天吧!', 'tag1')
INPUT = tkinter.StringVar()
INPUT.set('')
entryIuput = tkinter.Entry(root1, width=120, textvariable=INPUT)
entryIuput.place(x=5,y=320,width=580,height=170)
# 在線用戶列表
listbox1 = tkinter.Listbox(root1)
listbox1.place(x=510, y=0, width=130, height=320)
def send(*args):
message = entryIuput.get() + '~' + user + '~' + chat
s.send(message.encode())
INPUT.set('')
sendButton = tkinter.Button(root1, text ="\n發(fā)\n\n\n送",anchor = 'n',command = send,font=('Helvetica', 18),bg = 'white')
sendButton.place(x=585,y=320,width=55,height=300)
root1.bind('<Return>', send)
def receive():
global uses
while True:
data = s.recv(1024)
data = data.decode()
print(data)
try:
uses = json.loads(data)
listbox1.delete(0, tkinter.END)
listbox1.insert(tkinter.END, "當(dāng)前在線用戶")
listbox1.insert(tkinter.END, "------Group chat-------")
for x in range(len(uses)):
listbox1.insert(tkinter.END, uses[x])
users.append('------Group chat-------')
except:
data = data.split('~')
message = data[0]
userName = data[1]
chatwith = data[2]
message = '\n' + message
if chatwith == '------Group chat-------': # 群聊
if userName == user:
listbox.insert(tkinter.END, message)
else:
listbox.insert(tkinter.END, message)
elif userName == user or chatwith == user: # 私聊
if userName == user:
listbox.tag_config('tag2', foreground='red')
listbox.insert(tkinter.END, message, 'tag2')
else:
listbox.tag_config('tag3', foreground='green')
listbox.insert(tkinter.END, message,'tag3')
listbox.see(tkinter.END)
r = threading.Thread(target=receive)
r.start() # 開始線程接收信息
root1.mainloop()
s.close()關(guān)于使用Python怎么實(shí)現(xiàn)一個(gè)網(wǎng)絡(luò)聊天室功能問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道了解更多相關(guān)知識(shí)。
文章名稱:使用Python怎么實(shí)現(xiàn)一個(gè)網(wǎng)絡(luò)聊天室功能-創(chuàng)新互聯(lián)
分享URL:http://chinadenli.net/article38/cdoosp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信小程序、關(guān)鍵詞優(yōu)化、品牌網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、小程序開發(fā)、品牌網(wǎng)站建設(shè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容