具体实现
实现两个python文件,其中server.py
包含Manager
类,用于充当服务器记录用户的信息,并广播通话内容,实现私聊模式,管理成员的进入和退出。使用多线程服务多个用户。
client.py
文件包含Chatter
类,用于与Manager
类建立一对一关联,向管理员发送加入和退出请求。其中发送和退出分别使用不同的线程完成。
最后在用户退出之后log.txt文件可以记录用户的日志并保存到本地磁盘上。
代码实现
server.py
文件
import socket,time
from threading import Thread
class Manager:
def __init__(self,socket,addr,username):
self.ip = addr[0]
self.port = addr[1]
self.username = username
self.socket=socket
def sendMsg(self,msg,username):
try:
self.socket.send(("%s %s: %s" %(self.getTime(), username, msg)).encode("utf-8"))
return True
except:
return False
def recv(self,mtu=1024):
try:
data = self.socket.recv(mtu).decode("utf-8")
if data == "quit" or not data:
return False
return data
except:
return False
def close(self):
try:
self.socket.close()
return True
except:
return False
def getId(self):
return "%s-%s" % (self.ip,self.port)
def getTime(self):
return str(time.strftime("%Y-%m-%d %H:%M:%S"))
def new_client(c):
try:
print("%s(%s) 尝试连接" %(c.ip,c.port))
file = open('log.txt','a')
file.write("%s(%s) 尝试连接\n" %(c.ip,c.port))
data = c.recv()
if not data:
return
c.username = data
print("用户%s %s(%s)已连接" %(c.username,c.ip,c.port))
file.write("用户%s %s(%s)已连接\n" %(c.username,c.ip,c.port))
iports[c.username] = f'{c.ip}-{c.port}'
c.socket.send("已连接".encode("utf-8"))
while True:
data = c.recv()
if not data:
break
elif data.split(' ')[0] =='@':
c.sendMsg(data,c.username)
clients[iports[data.split(' ')[1]]].sendMsg(data,c.username)
else:
print("用户%s %s(%s) 发送了: %s" % (c.username,c.ip, c.port, data))
file.write("用户%s %s(%s) 发送了: %s\n" % (c.username,c.ip, c.port, data))
Manager.broadcast(data,c.username)
except socket.errno as e:
print("Socket error: %s" % str(e))
except Exception as e:
print("Other exception: %s" % str(e))
finally:
print("%s(%s) 断开连接" % (c.ip, c.port))
file.write("%s(%s) 断开连接\n" % (c.ip, c.port))
#file.close()
c.close()
clients.pop(c.getId())
def broadcast(msg,username):
for c in clients.values():
c.sendMsg(msg,username)
def main(port):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
host = "127.0.0.1"
server.bind((host, port))
# 监听客户端
server.listen(10)
print("服务器已开启,正在监听{}".format(server.getsockname()))
while True:
# 接受客户端连接
conn, addr = server.accept()
c = Manager(conn,addr,"")
clients[c.getId()] = c
t = Thread(target=Manager.new_client, args=(c,))
t.start()
if __name__ == "__main__":
clients = {}
iports = {}
main(2021)
print("服务器已关闭")
client.py
文件
import socket
import time
from threading import Thread
running = False
class Chatter:
def send(c):
time.sleep(0.5)
while True:
data = input('')
c.send(data.encode("utf-8"))
#file.write(data+'\n')
#file.close()
if data == "quit":
running = False
break
def recv(c,t2):
username = input("输入用户名:")
#file = open(f'{username}.txt','a')
#file.write("输入用户名:"+username+'\n')
c.send(username.encode("utf-8"))
t2.start()
while running:
try:
data = c.recv(1024).decode("utf-8")
if not data:
break
print(data)
#file.write(data+'\n')
#file.close()
except:
break
if __name__ == "__main__":
ip = "127.0.0.1"
addrs = socket.getaddrinfo(socket.gethostname(), None)
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
client.settimeout(0.1)
client.close()
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 导入 socket 模块
try:
client.connect((ip, 2021))
running = True
t2 = Thread(target=Chatter.send, args=(client,))
t1 = Thread(target=Chatter.recv, args=(client,t2))
t1.start()
t1.join()
t2.join()
except:
pass
finally:
print("连接已被关闭")
#file.close()
client.close()
网友评论