Socket Small Project

Hi, I’ve been writing my first client-server-protocol project and I keep getting this error.

Traceback (most recent call last):
  File "D:\SocketsServerClientProtocol\client26.py", line 43, in <module>
    main()
  File "D:\SocketsServerClientProtocol\client26.py", line 23, in main
    data = my_socket.recv(1024).decode()
           ^^^^^^^^^^^^^^^^^^^^
ConnectionAbortedError: [WinError 10053] An established connection was aborted by the software in your host machine

what does this mean?

It means what it says – not that that helps very much :slight_smile:
Without knowing what your script is doing or how your host, server and client are set up, what kind of frameworks you’re using, it’s not possible to tell what specifically triggered this. The following StackOverflow post gives a general overview of possible causes and suggestions about how to debug/fix it: python - ConnectionAbortedError: [WinError 10053] An established connection was aborted by the software in your host machine - Stack Overflow

2 Likes

This is my entire code if it helps :confused:

Client:

import socket
import protocol


def main():
    my_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    my_socket.connect(("127.0.0.1", protocol.PORT))

    while True:
        user_input = input("Enter command: \n")
        # Check if user entered a valid command as defined in protocol
        valid_cmd = protocol.check_cmd(user_input)
        if valid_cmd:
            user_input = protocol.create_msg(user_input)
            my_socket.send(user_input.encode())
            if protocol.get_msg(user_input)[1] == "EXIT":
                break
            data = my_socket.recv(4).decode()
            if protocol.get_msg(data):
                print(data)
            else:
                print("Response not valid\n")
        else:
            print("Not a valid command")

            # If the command is valid:
            # 1. Add length field ("RAND" -> "04RAND")
            # 2. Send it to the server
            # 3. If command is EXIT, break from while loop
            # 4. Get server's response
            # 5. If server's response is valid, print it
    print("Closing\n")
    # Close socket
    my_socket.close()

Server:

import datetime
import socket
import protocol
import random


def create_server_rsp(cmd):
    """Based on the command, create a proper response"""
    response_msg = ""
    if protocol.check_cmd(cmd):
        if cmd == "TIME":
            response_msg = datetime.datetime.now()
        elif cmd == "NAME":
            response_msg = "My name is Server"
        elif cmd == "RAND":
            response_msg = random.randint(1, 10)
        elif cmd == "EXIT":
            response_msg = "EXIT"
    return response_msg


def main():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.bind(("0.0.0.0", protocol.PORT))
    server_socket.listen()
    print("Server is up and running")
    (client_socket, client_address) = server_socket.accept()
    print("Client connected")
    while True:
        # Get message from socket and check if it is according to protocol
        valid_msg, cmd = protocol.get_msg(client_socket)
        if valid_msg:
            print(client_socket.recv(1024).decode())
            if protocol.check_cmd(cmd):
                response = create_server_rsp(cmd)
            else:
                response = "Wrong command"
        else:
            response = "Wrong protocol"
            client_socket.recv(1024)  # Attempt to empty the socket from possible garbage
        # Handle EXIT command, no need to respond to the client
        if response == "EXIT":
            break
        client_socket.send(valid_msg.encode())

        # Send response to the client

    print("Chck")
    # Close sockets
    client_socket.close()
    server_socket.close()

Protocol:

def check_cmd(data):
    """Check if the command is defined in the protocol (e.g. RAND, NAME, TIME, EXIT)"""
    if data in ["RAND", "NAME", "TIME", "EXIT"]:
        return True


def create_msg(data):
    """Create a valid protocol message, with length field"""
    length_msg = str(len(data))
    if int(length_msg) > 2:
        zfill_length = length_msg.zfill(2)
        user_input = zfill_length + data
    else:
        user_input = length_msg + data
    return user_input


def get_msg(my_socket):
    """Extract message from protocol, without the length field
       If length field does not include a number, returns False, "Error" """
    if not my_socket[1].isdigit():
        return False, "ERROR"
    else:
        return True, my_socket[2:]

This looks dubious. I’m not sure if I’m misreading your code here, but a socket can’t normally be subscripted in this way.

To create a protocol like this, you’re probably going to need to build some sort of read buffer. There are libraries that can help you with this, but to do it yourself, you’d want something like this:

  • Client socket connects. Initialize the buffer to an empty string (buf = b"")
  • Check the buffer. Does it contain a valid message? By your current protocol, this would mean having at least two bytes in the buffer, both of which are digits, and as many more bytes after it as those digits imply.
  • If it does not, get more data from the socket:
if data := client_socket.recv(1024):
    buf += data
else:
    client is disconnected, cope with that somehow
  • Go back and see if you have a message.
  • Once you have a message, remove it from the buffer. There might be additional data (a non-empty buffer) or not (buffer is back to an empty string), either is fine.
  • Process the message, and go back to the top.

Again, there are lots of libraries out there that can help, but I’ll be honest, there’s a lot of value in doing this yourself and understanding what’s actually going on here :slight_smile:

1 Like