首页 > 解决方案 > Python Socket 编码和解码客户端数据

问题描述

我正在尝试创建消息服务器类型的东西。连接到服务器客户端并尝试输入用户名后,它会给出错误:

“需要一个类似字节的对象,而不是'str'”

而且我不确定我是否对编码和解码功能处理不当。

import socket, time, sys, threading 
class Server:
    def __init__(self, port):
        while True: 
            try: 
                self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                self.port = port
                self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
                self.socket.bind(('127.0.0.1',port))
                self.clients = []
                self.usernames = []
                print('Successfully bound socket!')
                break
            except: 
                print('Error binding, retrying....')
                time.sleep(5)
    def close(self): 
        self.socket.close()
    
    def commands(self): 
        while True: 
            command = input()
            if command.lower() in ['exit', 'end', 'quit', 'q']: 
                print('Closing Session.....')
                server.close(), sys.exit()

    def broadcast(self, message): 
        for client in self.clients: 
            client.send(message)

    def handle(self, client): 
        while True: 
            try: 
                message = client.recv(1024)
                server.broadcast(message)
            except: 
                index = self.clients.index(client)
                self.clients.remove(client)
                client.close()
                username = self.usernames[index]
                server.broadcast(f'{username.decode("ascii")} has left!')
                self.usernames.remove(username)
                break

    def receive(self, client, addr): 
        while True:
            print(f'New Socket Connection: {addr}')
            try: 
                client.send('USERNAME: '.encode('ascii'))
                username = client.recv(1024).decode('ascii')
                self.usernames.append(username)
                self.clients.append(client)
                print(f'Username is: {username}')
                server.broadcast(f'{username.encode("ascii")} has connected.')
                client.send('Connected to the server!'.encode('ascii'))
                thread = threading.Thread(target=handle, args=(client,))
                thread.start()
            except Exception as e:
                print(e) 
                print('Closed early! (Or wrong values entered!)')
                socket.close()
                print(f'Client {addr} closed.')
            client.send()

    def listen(self): 
        self.socket.listen(5)
        print('Listening for new connections....')
        while True: 
            client, addr = self.socket.accept()
            client.settimeout(60)
            server.receive(client, addr)

server = Server(4545)

try: 
    server.listen()
except: 
    server.close()

问题来自接收功能:

def receive(self, client, addr): 
        while True:
            print(f'New Socket Connection: {addr}')
            try: 
                client.send('USERNAME: '.encode('ascii'))
                username = client.recv(1024).decode('ascii')
                self.usernames.append(username)
                self.clients.append(client)
                print(f'Username is: {username}')
                server.broadcast(f'{username.encode("ascii")} has connected.')
                client.send('Connected to the server!'.encode('ascii'))
                thread = threading.Thread(target=handle, args=(client,))
                thread.start()
            except Exception as e:
                print(e) 
                print('Closed early! (Or wrong values entered!)')
                socket.close()
                print(f'Client {addr} closed.')
            client.send()

标签: pythonsocketsserver

解决方案


看看这部分代码:

def receive(self, client, addr): 
    while True:
        #[...]
        server.broadcast(f'{username.encode("ascii")} has connected.')

您只是在编码username但不是完整的字符串!

所以它应该是这样的:

#[...]
server.broadcast(f'{username} has connected.'.encode("ascii"))
#[...]

这是最终的工作代码:

import socket, time, sys, threading 
class Server:
    def __init__(self, port):
        while True: 
            try: 
                self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                self.port = port
                self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
                self.socket.bind(('127.0.0.1',port))
                self.clients = []
                self.usernames = []
                print('Successfully bound socket!')
                break
            except: 
                print('Error binding, retrying....')
                time.sleep(5)
    def close(self): 
        self.socket.close()
    
    def commands(self): 
        while True: 
            command = input()
            if command.lower() in ['exit', 'end', 'quit', 'q']: 
                print('Closing Session.....')
                server.close(), sys.exit()

    def broadcast(self, message): 
        for client in self.clients: 
            client.send(message)

    def handle(self, client): 
        while True: 
            try: 
                message = client.recv(1024)
                server.broadcast(message)
            except: 
                index = self.clients.index(client)
                self.clients.remove(client)
                client.close()
                username = self.usernames[index]
                server.broadcast(f'{username.decode("ascii")} has left!')
                self.usernames.remove(username)
                break

    def receive(self, client, addr): 
        while True:
            print(f'New Socket Connection: {addr}')
            try: 
                client.send('USERNAME: '.encode('ascii'))
                username = client.recv(1024).decode('ascii')
                self.usernames.append(username)
                self.clients.append(client)
                print(f'Username is: {username}')
                server.broadcast(f'{username} has connected.'.encode("ascii"))
                client.send('Connected to the server!'.encode('ascii'))
                thread = threading.Thread(target=handle, args=(client,))
                thread.start()
            except Exception as e:
                print(e) 
                print('Closed early! (Or wrong values entered!)')
                socket.close()
                print(f'Client {addr} closed.')
            client.send()

    def listen(self): 
        self.socket.listen(5)
        print('Listening for new connections....')
        while True: 
            client, addr = self.socket.accept()
            client.settimeout(60)
            server.receive(client, addr)

server = Server(4545)

try: 
    server.listen()
except: 
    server.close()

推荐阅读