Search code examples
pythonsocketsportbindlisten

Reuse the same socket to send and receive (Python)


I have written a simple script to send and receive messages using the Python socket module. I want to first send a message using sendMsg and then receive a response using listen. sendMsg works fine but when my server sends a response I receive the error:

"[WinError 10038] An operation was attempted on something that is not a socket"

I close the socket connection in sendMsg and then try to bind it in listen, but it's at this line that the error is produced. Please could someone show me what I am doing wrong!

import socket

port = 3400
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((socket.gethostname(), port))

def sendMsg():

    print("\nSending message:\n\n")
    msg = ("Sample text").encode("utf-8")
    s.send(msg)
    s.close()

def listen():

    s.bind(("", port))
    s.listen(1)

    serverSocket, info = s.accept()
    print("Connection from", info, "\n")
    while 1:
        try:            
            buf = bytearray(4000)
            view = memoryview(buf)
            bytes = serverSocket.recv_into(view, 4000)
            if bytes:
                stx = view[0]
                Size = view[1:3]
                bSize = Size.tobytes()
                nTuple = struct.unpack(">H", bSize)
                nSize = nTuple[0]
                message = view[0:3+nSize]
                messageString = message.tobytes().decode("utf-8").strip()
                messageString = messageString.replace("\x00", "")
            else:
                break
        except socket.timeout:
            print("Socket timeout.")
            break

sendMsg()

listen()

Note: I have implemented listen in a separate client and used the line

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

before s.bind() and s.connect(). This works OK. It would be nice to have it all in one client though.


Solution

  • As per the docs the socket.close() will close the socket and no further operations are allowed on it.

    So in your code this line s.close() is closing the socket.

    Because of that the s.bind(("", port)) will not work as the socket s is already closed!