1 设计内容
用Python语言编程实现一个基于UDP协议Socket/SocketServer架构的GUI聊天室程序。服务器为多进程/多线程并发, 客户端要求具备图形界面。
2 设计要求
1. 运行在Linux系统平台上
2. Python语言编程
3. 基于TCP/IP socket/socketserver编程
4. 多进程/多线程并发
5. 客户端使用GUI图形界面
3 设计过程及设计步骤
import socket
import threading
def broadcast_msg(udp_server,msg,addr,addr_list):
for each_addr in addr_list:
udp_server.sendto(msg.encode("utf-8"),each_addr)
udp_server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
udp_server.bind(("0.0.0.0",6666))
print("udp服务器正在运行中")
addr_list=[]
users={}
while True:
try:
msg,addr=udp_server.recvfrom(1024)
try:
msg=msg.decode("utf_8")
except:
msg=msg.decode("gbk")
if addr not in addr_list:
addr_list.append(addr)
name_s=msg;
users.setdefault(addr,name_s)
data='Welcome '+name_s+'!'
print(data)
data_s=''
else:
name_s=users.get(addr)
data_s=msg
data=name_s+': '+data_s
t=threading.Thread(target=broadcast_msg,args=(udp_server,data,addr,addr_list))
t.start()
if msg.upper()[0:3]=='BYE':
if addr in addr_list:
addr_list.remove(addr)
del(users[addr])
print("%s退出聊天室"%users.get(addr))
continue
else:
continue
except Exception as ret:
print(ret)
udp_server.close()
- 2 基于socketserver的服务器端程序设计
import socketserver
class Chat_server(socketserver.DatagramRequestHandler):
def handle(self):
try:
(data_b,conn)=self.request
print("client_address:",self.client_address)
print("data_b=",data_b)
if c_address.count(self.client_address)==0:
conns.setdefault(self.client_address,conn)
c_address.append(self.client_address)
name_s=data_b.decode('utf-8')
users.setdefault(self.client_address,name_s)
data='Welcome '+name_s+'!'
data_s=''
else:
name_s=users.get(self.client_address)
data_s=data_b.decode('utf-8')
data=name_s+': '+data_s
for c_addr in c_address:
print(u"{0} sento {1}".format(conns.get(c_addr),c_addr))
conns.get(c_addr).sendto(data.encode("utf-8"),c_addr)
if data_s.upper()[0:3]=='BYE':
print('%s is exited!'%name_s)
del(conns[self.client_address])
c_address.remove(self.client_address)
del(users[self.client_address])
print('data=',data)
except Exception as e:
print('Error is ',e)
conns={}
c_address=[]
users={}
ip='0.0.0.0'
server=socketserver.ThreadingUDPServer((ip,6666),Chat_server)
print('udp服务器正在运行中.....')
server.serve_forever()
import socket
import threading
import datetime
import sys
import tkinter as tk
def send_msg():
txt=bt_txt.get()
if txt=='Logon':
bt_txt.set('send')
msg=et_txt.get()
et_txt.set('')
print('msg=',msg)
msg_b=msg.encode('utf-8')
s.sendto(msg_b,(ip,6666))
if msg.upper()[0:3]=='BYE':
chat_send.config(state=tk.DISABLED)
s.close()
sys.exit()
root.destroy()
def receive_msg():
while True:
try:
data_b=s.recv(1024)
data_s=data_b.decode('utf-8')
print('data_s=',data_s)
if data_s!="":
time=u"time:{0}".format(datetime.datetime.now().strftime("%Y.%m.%d-%H:%M:%S")).encode("utf-8")
chat_list.insert(0,data_s)
chat_list.see(0)
chat_list.insert(0,time)
chat_list.see(0)
except:
print("exit bye")
break
ip='192.168.1.4'
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.connect_ex((ip,6666))
t=threading.Thread(target=receive_msg)
t.start()
root=tk.Tk()
root.title('Chatting room')
root.geometry('300x350')
root.resizable(width=False,height=True)
fm=tk.Frame(root,width=300,height=300)
scrl=tk.Scrollbar(fm)
chat_list=tk.Listbox(fm,height=300,width=300,selectmode=tk.BROWSE)
chat_list.configure(yscrollcommand=scrl.set)
scrl['command']=chat_list.yview
bt_txt=tk.StringVar(value='Logon')
et_txt=tk.StringVar(value='')
chat_txt=tk.Entry(root,bd=5,width=280,textvariable=et_txt)
chat_send=tk.Button(root,textvariable=bt_txt,command=send_msg)
scrl.pack(side=tk.RIGHT,fill=tk.Y)
chat_txt.pack()
chat_list.pack()
chat_send.pack()
fm.pack()
root.mainloop()
4 测试运行
- 运行socketserver方式的chat_UDP_s.py程序和3个chat_UDP_s.py的客户端程序,运行结果如下:
- socketserver方式下,第一个客户端输入bye结束第一个客户端的会话,并且第一个客户端结束服务程序,如下图所示:
- 运行socket方式的chat_UDP_s.py程序和3个chat_UDP_s.py的客户端程序,运行结果如下: