oRedNCS
oRedNCS

Reputation: 99

Python Socket Encoding and Decoding Client Data

I'm trying to create a message server type of thing. After connecting to the server client-side and attempting to type in a username, it gives the error:

"a bytes-like object is required, not 'str'"

And I wasn't sure If I was mishandling the encoding and decoding functions or not.

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()

The problem occurs from the receive function:

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()

Upvotes: 1

Views: 2170

Answers (1)

CopyrightC
CopyrightC

Reputation: 863

Have a look at this part of code :

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

You're just encoding the username but not the complete string!

So it should be something like this :

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

Here's the final working code:

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()

Upvotes: 1

Related Questions