实现一个可以同时多人在线的网络聊天室软件
一、设计思路,程序流程图
1) 用户通过用户名,密码登录聊天室
2) 在每一条聊天内容之前,显示发出这条聊天内容的用户名。
3) 聊天室可以用web,客户端,或者手机APP方式实现。
流程图如下:
二、程序源代码
#客户端程序client.py
from tkinter import *
import tkinter.font as tkFont
import datetime
import time
import threading
import socket
global name
global entry_room
data = {'张三':'10000','李四':'10001','王五':'10002'}
entry_room=0
def Sign():
def Check():
global name,entry_room
num = num_entry.get()
pawd = pawd_entry.get()
if num in data:
if pawd == data[num]:
#msgbox.showinfo('温馨提示', '成功登录')
if(enterroom()):
print("成功登录")
name = num+': '
entry_room = 1
top.destroy()
else:
#print("登录失败")
msgbox.showinfo('温馨提示', '登录失败')
else:
#print("密码错误")
msgbox.showinfo('温馨提示', '密码错误')
else:
msgbox.showinfo('温馨提示', '用户不存在')
#print("用户不存在")
def enterroom():
try:
udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
#绑定本地信息
udp_socket.bind(('127.0.0.1',10000))
udp_socket.sendto('login'.encode('utf-8'),('127.0.0.1',9999))
recv_data = udp_socket.recvfrom(1024)
if(recv_data):
#print(recv_data)
udp_socket.close()
return 1
except:
udp_socket.close()
return 0
top = Tk()
top.title("登录界面")
frame_sign = Frame(width=285, height=115)
ft = tkFont.Font(family='NSimSun', size=13)
label_num = Label(frame_sign,text='账号:',font=ft)
label_pawd = Label(frame_sign,text='密码:',font=ft)
num_entry = Entry(frame_sign,font=ft)
pawd_entry = Entry(frame_sign,font=ft)
button_sign = Button(frame_sign,text='登录',font=ft,command=Check)
button_quit = Button(frame_sign,text='退出',font=ft,command=top.destroy)
frame_sign.grid(row=0, column=0,padx=4, pady=0)
label_num.place(x=10,y=7)
label_pawd.place(x=10,y=45)
num_entry.place(width=200,height=25,x=70,y=7)
pawd_entry.place(width=200,height=25,x=70,y=45)
button_sign.place(width=80,height=25,x=50,y=80)
button_quit.place(width=80,height=25,x=150,y=80)
top.mainloop()
def Chatroom():
def record_clear():
text_msglist.delete('0.0',END)
#success = '- - - - - - - - - - - - - - - - 正 在 聊 天 - - - - - - - - - - - - - - - -'
#text_msglist.insert(END,success)
def recv_msg(udp_socket,text_msglist):
while 1:
recv_data = udp_socket.recvfrom(1024)
recv_msg = recv_data[0].decode('utf-8')
time_now = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))+'\n'
text_msglist.insert(END,time_now)
text_msglist.insert(END,recv_msg+'\n\n')
text_msglist.see(END)
def start_recv():
t_recv = threading.Thread(target = recv_msg,args = (udp_socket,text_msglist))
#接收信息
t_recv.start()
def msg_clear():
global name
#global dest_ip,dest_port
send_data = text_msg.get('0.0',END)
if(send_data!='\n'):
#time_now = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))+'\n'
#text_msglist.insert(END,time_now)
#text_msglist.insert(END,'我:'+send_data+'\n')
send_data = name+send_data
udp_socket.sendto(send_data.encode('utf-8'),('127.0.0.1',9999))
text_msg.delete('0.0',END)
text_msglist.see(END)
#创建套接字
udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
udp_socket.sendto('newconn'.encode(‘utf-8’))
#绑定本地信息
udp_socket.bind(('127.0.0.1',10000))
root = Tk()
root.title('聊天室界面')
#创建几个frame作为容器
frame_left_top = Frame(width=565, height=310, bg='white')
frame_left_center = Frame(width=565, height=100, bg='white')
frame_left_bottom = Frame(width=565, height=34, bg='white')
##创建需要的几个元素
text_msglist = Text(frame_left_top)
success = '- - - - - - - - - - - - - - - - 加 入 成 功 - - - - - - - - - - - - - - - -'
text_msglist.insert(END,success)
start_recv()
text_msg = Text(frame_left_center)
button_sendmsg = Button(frame_left_bottom,text='发 送 信 息',command=msg_clear)
button_msgclear = Button(frame_left_bottom,text='删除聊天记录',command=record_clear)
#使用grid设置各个容器位置
frame_left_top.grid(row=0, column=0, padx=4, pady=5)
frame_left_center.grid(row=1, column=0, padx=4, pady=0)
frame_left_bottom.grid(row=2, column=0,padx=4, pady=0)
frame_left_top.grid_propagate(0)
frame_left_center.grid_propagate(0)
frame_left_bottom.grid_propagate(0)
#把元素填充进frame
text_msglist.grid()
text_msg.grid()
button_sendmsg.place(width=150,height=30,x=410,y=0)
button_msgclear.place(width=160,height=30,x=4,y=0)
#主事件循环
root.mainloop()
def main():
global entry_room
#entry_room = 0
Sign()
if entry_room:
Chatroom()
print("退出聊天室")
if __name__ == '__main__':
main()
#服务器程序serve.py
import socket
allusers=[]
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.bind(('127.0.0.1', 9999))
while True:
recv_data = server.recvfrom(1024)
txtdata = recv_data[0]
if recv_data[1] not in allusers:
allusers.append(recv_data[1])
if txtdata!=b'newconn':
for i in allusers:
server.sendto(txtdata,i)