服务器端:
import socket
from threading import Thread
import time
#server不需要界面
class Server:
#初始化方法
def __init__(self):
self.server=socket.socket()#默认不写是ipv4,tcp协议
self.server.bind(("127.0.0.1",10008))
self.server.listen(5)#最大监听数量5个
#所有的客户端
self.clients=[]
#用户名与id的绑定信息
self.clients_name_ip={}
self.get_conn()
#监听所有客户端的连接
def get_conn(self):
while True:
#获取客户端信息
client,address=self.server.accept()
print(address)
data="与服务器连接成功,请你输入昵称才可以聊天"
#server与client通信,发消息send(encode)和收消息recv(decode)
client.send(data.encode())
#把连接的用户添加到服务器的用户列表中
self.clients.append(client)
#服务器启动多个线程,处理每个客户端的消息
Thread(target=self.get_msg,args=(client,self.clients,self.clients_name_ip,address)).start()
#进行所有客户端消息处理
def get_msg(self,client,clients,clients_name_ip,address):
#接收客户端发来的昵称
name=client.recv(1024).decode()
print("from client "+name)
#将昵称与ip绑定
clients_name_ip[address]=name
#循环监听所有客户端的消息
while True:
#获取所有客户端发送的消息
try:
recv_data=client.recv(1024).decode()
except Exception as e:
self.close_client(client,address)
break
#如果用户退出就输入q
if recv_data.upper()=='Q':
self.close_client(client, address)
break
for c in clients:
c.send((clients_name_ip[address]+' '+time.strftime("%x")+'\n'+recv_data).encode())
#关闭资源
def close_client(self,client,address):
self.clients.remove(client)
client.close()
print(self.clients_name_ip[address]+'已经离开')
for c in self.clients:
c.send((self.clients_name_ip[address]+'已经离开').encode())
if __name__=='__main__':
Server()
客户端:
from PyQt5 import QtGui
from PyQt5.QtGui import QFont
from PyQt5.QtWidgets import *
import sys
import socket
from threading import Thread
class Client(QWidget):
#初始化界面
def __init__(self):
QWidget.__init__(self)
#设置窗口的大小与位置
self.setGeometry(600,300,360,300)
#设置标题
self.setWindowTitle('聊天室')
#添加背景
palette=QtGui.QPalette()#构建模板
bg=QtGui.QPixmap(r'img/background.png')
palette.setBrush(self.backgroundRole(),QtGui.QBrush())
self.setPalette(palette)
self.add_ui()
#与服务器连接
self.client=socket.socket()
self.client.connect(('127.0.0.1',10008))
self.work_thread()
#设置界面中的元素
def add_ui(self):
#多行文本显示,显示所有的聊天信息
self.content=QTextBrowser(self)
self.content.setGeometry(30,30,300,150)
#单行文本,消息发送框
self.message=QLineEdit(self)
self.message.setPlaceholderText(u'输入发送内容')#占位符
self.message.setGeometry(30,200,300,30)
#发送按钮
self.button=QPushButton('发送',self)
self.button.setFont(QFont('微软雅黑',10,QFont.Bold))
self.button.setGeometry(270,250,60,30)
#发送消息
def send_msg(self):
msg=self.message.text()
self.client.send(msg.encode())
if msg.upper()=='Q':
self.client.close()
self.destroy()
self.message.clear()#发完后要清空输入框
#接收消息
def recv_msg(self):
while True:
try:
data=self.client.recv(1024).decode()
print(data)
data=data+'\n'
self.content.append(data)
except:
exit()
#消息与槽的处理
def btn_send(self):
self.button.clicked.connect(self.send_msg)
#线程处理 匿名类
def work_thread(self):
Thread(target=self.btn_send).start()
Thread(target=self.recv_msg).start()
if __name__ == '__main__':
app=QApplication(sys.argv)
client=Client()
client.show()
sys.exit(app.exec())