简单聊天asyncio.Protocol,将数据从传输流保存到文件中

时间:2019-03-26 20:26:29

标签: python-3.x python-asyncio

我正在进行简单的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()

0 个答案:

没有答案