我正在进行简单的asyncio.Protocol服务器-客户端聊天。剩下要做的就是保存聊天记录,以便每个设置了昵称的新客户端都可以获取聊天记录。
我不知道如何避免在数据流中重复消息。我试图将服务器实例中显示的内容捕获到文件中。我在带有插座和踏板的版本中没有这个问题。 某些事情使我难以理解,这绝对是陈词滥调。
CLIENT.py
import asyncio
import threading
import socket
import sServer
import random
class Client(asyncio.Protocol):
def __init__(self):
self.name = None
def connection_made(self, transport):
self.name = set_nickname()
print("Type your message below or 'EXIT' to quit")
self.transport = transport
try:
with open('history.txt', 'rt') as history:
content = history.read()
print(content)
except FileNotFoundError:
pass
transport.write(('USR:'+self.name).encode())
thread = threading.Thread(target=self.handle_input, daemon=True)
thread.start()
def data_received(self, data):
print(data.decode())
def eof_received(self):
print("Connection lost...")
def connection_lost(self, exc):
self.transport.close()
def handle_input(self):
while True:
message = input('ME> ')
if message == 'EXIT':
self.transport.write(message.encode())
# elif message == 'HIST':
# self.load_history()
else:
self.transport.write(('MSG:'+message).encode())
def set_nickname():
try:
#user = 'hardcoded'
print("Type your nickname: ")
user = input().strip()
print("Hello {}".format(user))
client_name = socket.gethostname()
ip = socket.gethostbyname(client_name)
# create random n
rest = random.randrange(1, 100, 1)
# for local purpose and testing multiply clients
client_ip = "@{}-{}".format(ip, str(rest))
user = user + client_ip
return user
except:
pass
def main():
loop = asyncio.get_event_loop()
coroutine = loop.create_connection(Client, sServer.HOST, sServer.PORT)
loop.run_until_complete(coroutine)
loop.run_forever()
loop.close()
if __name__ == "__main__":
main()
SERVER.py
import asyncio
import json
import sys
import os.path
HOST = '127.0.0.1'
PORT = 6666
active_users = []
history = {}
class Server(asyncio.Protocol):
""" Overriding Protocol methods:
connection_made
data_received
connection_lost
"""
def connection_made(self, transport):
self.transport = transport
self.address = transport.get_extra_info('peername')
print('Connection from {}'.format(self.address))
def data_received(self, data):
stream = data.decode()
if stream.startswith("USR:"):
self.username = stream[4:]
add_user(self)
elif stream.startswith("MSG:"):
msg = stream[4:]
receive_message((self.username + ': ' + msg), self)
#update_history((self.username + ': ' + msg), self)
history.update({self.username: msg})
with open('history.txt', 'a+') as sample:
for save in [history]:
sample.write('{}\n'.format(save))
elif stream == 'EXIT':
remove_user(self)
self.transport.close()
def add_user(user):
active_users.append(user)
receive_message(user.username + ' has joined!', user)
def remove_user(user):
active_users.remove(user)
receive_message(user.username + ' has left.', user)
def receive_message(msg, author):
print(msg)
for user in active_users:
# don't show user's own messages in session
if user is not author:
user.transport.write(msg.encode())
def main():
loop = asyncio.get_event_loop()
coroutine = loop.create_server(Server, HOST, PORT)
server = loop.run_until_complete(coroutine)
print('Server established on {}'.format(server.sockets[0].getsockname()))
try:
loop.run_forever()
except KeyboardInterrupt:
if os.path.exists('history.txt'):
try:
os.remove('history.txt')
sys.exit()
except OSError:
pass
finally:
server.close()
loop.close()
if __name__ == '__main__':
main()