python茶话会学习解决问题:data argument must be byte-ish (%r)‘

参考:待csdn收藏服务恢复后添加,或者自行去找

可能的报错包含但不限于:

error: uncaptured python exception, closing channel <__main__.ChatSession connected 127.0.0.1:61630 at 0x108d2b640> (<class 'TypeError'>:argument should be integer or bytes-like object, not 'str' [/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/lib/python3.8/asyncore.py|read|83] [/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/lib/python3.8/asyncore.py|handle_read_event|420] [/usr/local/Cellar/python@3.8/3.8.5/Frameworks/Python.framework/Versions/3.8/lib/python3.8/asynchat.py|handle_read|161])

解决方法:

首先,python3中需要将类似 session.push(line+b'\r\n')的方法,字符串前面全部加b

然后,将所有传数据的进行加密解密 self.data.append(data.decode('utf-8'))

检查修改完成后,如果还有报错,根据报错的位置去对应的地方修改便可

修改后可执行的python3版本代码如下

import asyncore
import socket
from asynchat import async_chat
from asyncore import dispatcher

PORT = 5005
NAME = 'TestChat'


class ChatSession(async_chat):
    """
    一个负责处理服务器和单个用户间连接的类
    """

    def __init__(self, server, sock):
        ## 标准的设置任务:
        async_chat.__init__(self, sock)
        self.server = server
        self.set_terminator(b'\r\n')
        self.data = []
        # 问候用户:
        self.push(b'Welcome to %s\r\n'%self.server.name.encode('utf-8'))
        # self.push('Wlecome')

    def collect_incoming_data(self, data):
        self.data.append(data.decode('utf-8'))

    def found_terminator(self):
        line = ''.join(self.data)
        self.data = []
        # print(line)
        self.server.broadcast(line.encode('utf-8'))

    def handle_close(self):
        async_chat.handle_close(self)
        self.server.disconnect(self)


class ChatServer(dispatcher):
    def __init__(self, port,name):
        dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.set_reuse_addr()  # 重用原来的地址(具体地说是端口号),即便未妥善关 闭服务器亦如此。如果不调用set_reuse_addr,可能需要等待一段时间才能重启服务器
        self.bind(('', port))  # ''代表localhost
        self.listen(5)
        self.name = name
        self.sessions = []

    def disconnect(self,session):
        self.sessions.remove(session)

    def broadcast(self,line):
        for session in self.sessions:
            session.push(line+b'\r\n')

    def handle_accept(self):
        conn, addr = self.accept()
        self.sessions.append(ChatSession(self,conn))


if __name__ == "__main__":
    s = ChatServer(PORT,NAME)
    try:
        asyncore.loop()
    except KeyboardInterrupt:
        print()

python3复杂版茶话会

# -*- coding: utf-8 -*- 
# @Time : 2020/11/9 11:31 上午 
# @Author : lixia
# @File : chartserver.py 
# @desc:一个更复杂些的聊天服务器  python2版 https://blog.csdn.net/orangleliu/article/details/8837539
import asyncore
import socket
from asynchat import async_chat
from asyncore import dispatcher

# from pygments.formatters import other

PORT = 5005
NAME = 'TestChat'


class EndSession(Exception): pass


class CommandHandler:
    """
    类似于标准库中cmd.Cmd的简单命令处理程序
    """

    def unknown(self, session, cmd):
        session.push(b'Unknown command:%s\r\n'%cmd.encode('utf-8'))

    def handle(self, session, line):
        '处理从指定会话收到的行'
        if not line.strip(): return
        # 提取命令:
        parts = line.split(' ', 1)
        print("parts:",parts)
        cmd = parts[0]
        print("cmd:",cmd)
        try:
            line = parts[1].strip()
        except IndexError:
            line = ''
        meth = getattr(self, 'do_' + cmd, None)
        try:
            # 假定它是可调用的:
            meth(session, line)
        except TypeError as e:
            print(e)
            # 如果是不可调用的,就响应未知命令:
            self.unknown(session, cmd)


class Room(CommandHandler):
    """
    可能包含一个或多个用户(会话)的通用环境。它负责基本的命令处理和广播
    """

    def __init__(self, server):
        self.server = server
        self.sessions = []

    def add(self, session):
        """
         '有会话(用户)进入聊天室'
        :param session:
        :return:
        """
        self.sessions.append(session)

    def remove(self, session):
        """
         '有会话(用户)离开聊天室'
        :param session:
        :return:
        """
        self.sessions.remove(session)

    def broadcast(self, line):
        """将一行内容发送给聊天室内的所有会话"""
        for session in self.sessions:
            session.push(line)

    def do_logout(self, session, line):
        """
         响应命令logout
        :param session:
        :param line:
        :return:
        """
        raise EndSession


class LoginRoom(Room):
    """
    为刚连接的用户准备的聊天室
    """

    def add(self, session):
        Room.add(self, session)
        # 用户进入时,向他/她发出问候:
        self.broadcast(b'Welocome to %s\r\n'%self.server.name.encode('utf-8'))

    def unknown(self, session, cmd):
        # 除login和logout外的所有命令都会
        # 导致系统显示提示消息:
        session.push(b'Please login \r\nUse "login <nick>"\r\n')

    def do_login(self,session,line):
        name = line.strip().encode('utf-8')
        print(name)
        print(self.server.users)
        # 确保用户输入了用户名:
        if not name:
            session.push(b'Please enter a name\r\n')
        # 确保用户名未被占用:
        elif name in self.server.users:
            session.push(b'The name "%s" is taken \r\n'%name)
            session.push(b'Please try again \r\n')
        else:
            # 用户名没问题,因此将其存储到会话中并将用户移到主聊天室
            session.name = name
            session.enter(self.server.main_room)

class ChatRoom(Room):
    """
    为多个用户相互聊天准备的聊天室
    """

    def add(self,session):
        # 告诉所有人有新用户进入:
        self.broadcast(session.name+b' has entered the room\r\n')
        self.server.users[session.name]=session
        print(self.server.users)
        # super().add(session)
        Room.add(self,session)

    def remove(self, session):
        Room.remove(self,session)
        self.broadcast(session.name+b' has left the room\r\n')

    def do_say(self,session,line):
        self.broadcast(session.name+":".encode('utf-8')+line.encode('utf-8') +b"\r\n")

    def do_look(self,session,line):
        '处理命令look,这个命令用于查看聊天室里都有谁'
        session.push(b'The following are in this room:\r\n')
        for other in self.sessions:
            session.push(other.name+b"\r\n")

    def do_who(self,session,line):
        '处理命令who,这个命令用于查看谁已登录'
        session.push(b'The following are logged in:\r\n')
        for name in self.server.users:
            session.push(name+b"\r\n")

class LogoutRoom(Room):
    """
   为单个用户准备的聊天室,仅用于将用户名从服务器中删除
    """

    def add(self,session):
    # 将进入LogoutRoom的用户删除
        try:
            del self.server.users[session.name]
        except KeyError:
            pass

class ChatSession(async_chat):
    """
   单个会话,负责与单个用户通信
    """

    def __init__(self,server,sock):
        super().__init__(sock)
        self.server = server
        self.set_terminator(b"\r\n")
        self.data=[]
        self.name = None
        # 所有会话最初都位于LoginRoom中:
        self.enter(LoginRoom(server))

    def enter(self,room):
        # 自己从当前聊天室离开,并进入下一个聊天室
        try:
            cur = self.room
        except AttributeError:
            pass
        else:
            cur.remove(self)
        self.room = room
        room.add(self)

    def collect_incoming_data(self, data):
        self.data.append(data.decode('utf-8'))

    def found_terminator(self):
        line = ''.join(self.data)
        self.data=[]
        try:
            self.room.handle(self,line)
        except EndSession:
            self.handle_close()

    def handle_close(self):
        async_chat.handle_close(self)
        self.enter(LogoutRoom(self.server))

class ChatServer(dispatcher):
    """
   只有一个聊天室的聊天服务器
    """

    def __init__(self,port,name):
        super().__init__()
        self.create_socket(socket.AF_INET,socket.SOCK_STREAM)
        self.set_reuse_addr()
        self.bind(('',port))
        self.listen(5)
        self.name = name
        self.users={}
        self.main_room=ChatRoom(self)

    def handle_accept(self):
        conn,addr = self.accept()
        ChatSession(self,conn)

if __name__=="__main__":
    s = ChatServer(PORT,NAME)
    try:
        asyncore.loop()
    except KeyboardInterrupt:
        print()

结果图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值