The problem is that the process who owned the socket (your tcplistener application) did not perform a proper shutdown of the related connections and / or sockets. In such cases, the port is blocked for some time - or even until reboot - before it can be reused.
To avoid this, you have to perform a graceful shutdown. That should also let the clients don't send packets anymore (providing they are handling such cases properly too).
See also
Graceful Shutdown, Linger Options, and Socket Closure | Microsoft Docs[
^]. While that is about the Windows socket API C functions, it describes what has to be observed.
The problem you have is also described at
Using SO\_REUSEADDR and SO\_EXCLUSIVEADDRUSE | Microsoft Docs[
^]:
Quote:
This issue can become complicated because the underlying transport protocol may not terminate the connection even though the socket has been closed. Even after the socket has been closed by the application, the system must transmit any buffered data, send a graceful disconnect message to the peer, and wait for a corresponding graceful disconnect message from the peer. It is possible that the underlying transport protocol might never release the connection; for example, the peer participating in the original connection might advertise a zero-size window, or some other form of "attack" configuration. In such a case, the client connection remains in an active state despite the request to close it, since unacknowledged data remains in the buffer.
To avoid this situation, network applications should ensure a graceful shutdown by calling shutdown with the SD_SEND flag set, and then wait in a recv loop until zero bytes are returned over the connection. This guarantees that all data is received by the peer and likewise confirms with the peer that it has received all of the transmitted data, as well as avoiding the aforementioned port reuse issue.
Further help requires seeing much more of your code.