Search code examples
pythonjsonsocketstcp

Sending JSON object to a tcp listener port in use Python


I have a listener on a tcp localhost:

HOST = '127.0.0.1'  # The server's hostname or IP address
PORT = 8192         # The port used by the server
def client_socket():
    while 1:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind((TCP_IP,TCP_PORT))
        s.listen(1)
        while 1:
            print 'Listening for client...'
            conn, addr = s.accept()
            print 'Connection address:', addr
            data = conn.recv(BUFFER_SIZE)
            if data == ";" :
                conn.close()
                print "Received all the data"
                i=0
                for x in param:
                    print x
                #break
            elif data:
                print "received data: ", data
                param.insert(i,data)
                i+=1
                #print "End of transmission"
        s.close()

I am trying to send a JSON object to the same port on the local host:

HOST = '127.0.0.1'  # The server's hostname or IP address
PORT = 8192         # The port used by the server
def json_message(direction):

    local_ip = socket.gethostbyname(socket.gethostname())
    data = {
        'sender' : local_ip,
        'instruction' : direction
    }

    json_data = json.dumps(data, sort_keys=False, indent=2)
    print("data %s" % json_data)

    send_message(json_data)

    return json_data



def send_message(data):
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.connect((HOST, PORT))
        s.sendall(data)
        data = s.recv(1024)

    print('Received', repr(data))

However, I get a socket error:

socket.error: [Errno 98] Address already in use

What am I doing wrong? Will this work or do I need to serialize the JSON object?


Solution

  • There are a few problems with your code, but the one that will likely address your issue is setting the SO_REUSEADDR socket option with:

    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    

    after you create the socket (with socket.socket(...) but before you attempt to bind to an address (with s.bind().

    In terms of other things, the two "halves" of the code are pretty inconsistent -- like you copied and pasted code from two different places and tried to use them? (One uses a context manager and Python 3 print syntax while the other uses Python 2 print syntax...)

    But I've written enough socket programs that I can decipher pretty much anything, so here's a working version of your code (with some pretty suboptimal parameters e.g. a buffer size of 1, but how else would you expect to catch a single ;?)

    Server:

    import socket
    
    HOST = '127.0.0.1'  # The server's hostname or IP address
    PORT = 8192         # The port used by the server
    BUFFER_SIZE = 1
    
    def server_socket():
        data = []
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            s.bind((HOST,PORT))
            s.listen()
            while 1: # Accept connections from multiple clients
                print('Listening for client...')
                conn, addr = s.accept()
                print('Connection address:', addr)
                while 1: # Accept multiple messages from each client
                    buffer = conn.recv(BUFFER_SIZE)
                    buffer = buffer.decode()
                    if buffer == ";":
                        conn.close()
                        print("Received all the data")
                        for x in data:
                            print(x)
                        break
                    elif buffer:
                        print("received data: ", buffer)
                        data.append(buffer)
                    else:
                        break
    
    server_socket()
    

    Client:

    import socket
    import json
    
    HOST = '127.0.0.1'  # The server's hostname or IP address
    PORT = 8192         # The port used by the server
    
    def json_message(direction):
        local_ip = socket.gethostbyname(socket.gethostname())
        data = {
            'sender': local_ip,
            'instruction': direction
        }
    
        json_data = json.dumps(data, sort_keys=False, indent=2)
        print("data %s" % json_data)
    
        send_message(json_data + ";")
    
        return json_data
    
    
    
    def send_message(data):
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
            s.connect((HOST, PORT))
            s.sendall(data.encode())
            data = s.recv(1024)
    
        print('Received', repr(data))
    
    json_message("SOME_DIRECTION")