以下代码可以实现一个简易的python聊天室功能,在图形界面中我们输入消息,点击发送可以在服务器端与客户端显示
import tkinter
import tkinter.font as tkFont
import socket
import threading
import time
import sys
class ServerUI():
local="127.0.0.1"
port=5505
global serverSock
flag=False
#初始化类的相关属性的构造函数
def __init__(self):
self.root=tkinter.Tk()
self.root.title("Python 在线聊天-服务器端V1.0")
#窗口面板,用四个frame面板布局
self.frame=[tkinter.Frame(),tkinter.Frame(),tkinter.Frame(),tkinter.Frame()]
#显示消息Text右边的滚动条
self.chatTextScrollBar=tkinter.Scrollbar(self.frame[0])
self.chatTextScrollBar.pack(side=tkinter.RIGHT,fill=tkinter.Y)
#显示消息Text,并绑定上面的滚动条
ft=tkFont.Font(family='Fixdsys',size=11)
self.chatText=tkinter.Listbox(self.frame[0],width=70,height=18,font=ft)
self.chatText['yscrollcommand']=self.chatTextScrollBar.set
self.chatText.pack(expand=1,fill=tkinter.BOTH)
self.chatTextScrollBar['command']=self.chatText.yview()
self.frame[0].pack(expand=1,fill=tkinter.BOTH)
#标签,分开消息显示Text和消息输入Text
label=tkinter.Label(self.frame[1],height=2)
label.pack(fill=tkinter.BOTH)
self.frame[1].pack(expand=1,fill=tkinter.BOTH)
#输入消息Text的滚动条
self.inputTextScrollBar=tkinter.Scrollbar(self.frame[2])
self.inputTextScrollBar.pack(side=tkinter.RIGHT,fill=tkinter.Y)
#输入消息Text,并于滚动条绑定
ft=tkFont.Font(family='Fixdsys',size=11)
self.inputText=tkinter.Text(self.frame[2],width=70,height=8,font=ft)
self.inputText['yscrollcommand']=self.inputTextScrollBar.set
self.inputText.pack(expand=1,fill=tkinter.BOTH)
self.inputTextScrollBar['command']=self.chatText.yview()
self.frame[2].pack(expand=1,fill=tkinter.BOTH)
#发送消息按钮
self.sendButton=tkinter.Button(self.frame[3],text="发送",width=10,command=self.sendMessage)
self.sendButton.pack(expand=1,side=tkinter.BOTTOM and tkinter.RIGHT,padx=25,pady=5)
#关闭按钮
self.closeButton=tkinter.Button(self.frame[3],text='关闭',width=10,command=self.close)
self.closeButton.pack(expand=1,side=tkinter.RIGHT,padx=25,pady=5)
self.frame[3].pack(expand=1,fill=tkinter.BOTH)
#接收消息
def receiveMessage(self):
self.serverSock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.serverSock.bind((self.local,self.port))
self.serverSock.listen(15)
self.buffer=1024
self.chatText.insert(tkinter.END,'服务器已经准备就绪......')
#循环接收客户端请求
while True:
self.connection,self.address=self.serverSock.accept()
self.flag=True
while True:
self.cientMsg=self.connection.recv(self.buffer).decode("utf-8")
if not self.cientMsg:
continue
elif self.cientMsg=='Y':
self.chatText.insert(tkinter.END,'服务器已经与客户端建立连接...')
self.connection.send(b'Y')
elif self.cientMsg=='N':
self.chatText.insert(tkinter.END,'服务器与客户端建立连接失败...')
self.connection.send(b'N')
else:
theTime=time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())
self.chatText.insert(tkinter.END,'客户端'+theTime+"说:\n")
self.chatText.insert(tkinter.END,''+self.cientMsg)
def sendMessage(self):
message=self.inputText.get('1.0',tkinter.END)
theTime=time.strftime("%Y-%m-%d %H: %M: %S",time.localtime())
self.chatText.insert(tkinter.END,'服务器'+theTime+"说\n")
self.chatText.insert(tkinter.END,''+message+'\n')
if self.flag==True:
self.connection.send(message.encode())
else:
self.chatText.insert(tkinter.END,"你还没有与客户建立连接,客户端无法收到消息")
self.inputText.delete(0.0,message.__len__()-1.0)
def close(self):
sys.exit()
def startNewThread(self):
thread=threading.Thread(target=self.receiveMessage,args=())
thread.setDaemon(True)
thread.start()
def main():
server=ServerUI()
server.startNewThread()
server.root.mainloop()
if __name__=='__main__':
main()
import tkinter
import tkinter.font as tkFont
import socket
import threading
import time
import sys
class ClientUI():
local = '127.0.0.1'
port = 5505
global clientSock
flag=False
def __init__(self):
self.root=tkinter.Tk()
self.root.title("Python 在线聊天-客户端V1.0")
#窗口面板,用四个面板布局
self.frame=[tkinter.Frame(),tkinter.Frame(),tkinter.Frame(),tkinter.Frame()]
#以下为界面设计与服务器端相同
# 显示消息Text右边的滚动条
self.chatTextScrollBar = tkinter.Scrollbar(self.frame[0])
self.chatTextScrollBar.pack(side=tkinter.RIGHT, fill=tkinter.Y)
# 显示消息Text,并绑定上面的滚动条
ft = tkFont.Font(family='Fixdsys', size=11)
self.chatText = tkinter.Listbox(self.frame[0], width=70, height=18, font=ft)
self.chatText['yscrollcommand'] = self.chatTextScrollBar.set
self.chatText.pack(expand=1, fill=tkinter.BOTH)
self.chatTextScrollBar['command'] = self.chatText.yview()
self.frame[0].pack(expand=1, fill=tkinter.BOTH)
# 标签,分开消息显示Text和消息输入Text
label = tkinter.Label(self.frame[1], height=2)
label.pack(fill=tkinter.BOTH)
self.frame[1].pack(expand=1, fill=tkinter.BOTH)
# 输入消息Text的滚动条
self.inputTextScrollBar = tkinter.Scrollbar(self.frame[2])
self.inputTextScrollBar.pack(side=tkinter.RIGHT, fill=tkinter.Y)
# 输入消息Text,并于滚动条绑定
ft = tkFont.Font(family='Fixdsys', size=11)
self.inputText = tkinter.Text(self.frame[2], width=70, height=8, font=ft)
self.inputText['yscrollcommand'] = self.inputTextScrollBar.set
self.inputText.pack(expand=1, fill=tkinter.BOTH)
self.inputTextScrollBar['command'] = self.chatText.yview()
self.frame[2].pack(expand=1, fill=tkinter.BOTH)
# 发送消息按钮
self.sendButton = tkinter.Button(self.frame[3], text="发送", width=10, command=self.sendMessage)
self.sendButton.pack(expand=1, side=tkinter.BOTTOM and tkinter.RIGHT, padx=15, pady=8)
# 关闭按钮
self.closeButton = tkinter.Button(self.frame[3], text='关闭', width=10, command=self.close)
self.closeButton.pack(expand=1, side=tkinter.RIGHT, padx=15, pady=8)
self.frame[3].pack(expand=1, fill=tkinter.BOTH)
#接收消息
def receiveMessage(self):
try:
#建立socket连接
self.clientSock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.clientSock.connect((self.local,self.port))
self.flag=True
except:
self.flag=False
self.chatText.insert(tkinter.END,'你还没有与服务器建立连接,请检查服务器端是否开启')
return
self.buffer=1024
self.clientSock.send('Y'.encode())
while True:
try:
if self.flag==True:# 建立连接,接收服务器端消息
self.serverMsg=self.clientSock.recv(self.buffer).decode('utf-8')
if self.serverMsg=='Y':
self.chatText.insert(tkinter.END,'客户端已经与服务器建立连接.....')
elif self.serverMsg=='N':
self.chatText.insert(tkinter.END,'客户端与服务器建立连接失败......')
elif not self.serverMsg:
continue
else:
theTime = time.strftime("%Y-%m-%d %H: %M: %S", time.localtime())
self.chatText.insert(tkinter.END, '服务器端' + theTime + "说:\n")
self.chatText.insert(tkinter.END, '' + self.serverMsg)
else:
break
except EOFError as msg:
raise msg
self.clientSock.close()
break
def sendMessage(self):
# 得到用户在Text中输入的消息
message=self.inputText.get('1.0',tkinter.END)
#格式化当前的时间
theTime = time.strftime("%Y-%m-%d %H: %M: %S", time.localtime())
self.chatText.insert(tkinter.END, '客户端' + theTime + "说:\n")
self.chatText.insert(tkinter.END, '' + message+'\n')
if self.flag==True:
self.clientSock.send(message.encode())
else:
#socket连接没有建立,提示用户
self.chatText.insert(tkinter.END,'你还未与服务器端建立连接,服务器端无法收到你发送的消息\n')
#清空用户在Text中输入的消息
self.inputText.delete(0.0,message.__len__()-1.0)
def close(self):
sys.exit()
#启动线程接收服务器端的消息
def startNewThread(self):
# 启动一个新线程来接收服务器的消息
#args是传递给线程函数的参数,receiveMessage函数不需要参数,就传一个空元组
thread=threading.Thread(target=self.receiveMessage,args=())
thread.setDaemon(True)
thread.start()
def main():
client=ClientUI()
client.startNewThread()
client.root.mainloop()
if __name__=='__main__':
main()
参考书籍:
Pyhon程序设计——从基础到开发