Search code examples
visual-c++winsock2

How to get socket states from socket winsock2


Hi I'm new to C++ winsock2 sockets and I've been stuck at this for a while.

How do I get if a socket is connected, bound, listening or closed from the socket/file descriptor passed as an argument.

Note : I want to figure out the socket state without attempting to bind/connect/listen/closesocket because that will return a result and perform the operation. Example : if I wanted to check whether a socket is connected to a server I should attempt to connect and get the result which I don't want.

I am trying to achieve something like this.

// Using Winsock2 API.
bool isSocketBound(SOCKET s) {
    // Check if socket is bound without attempting to bind.
    // The code which I'm not able to figure out.
    return isBound;
}

// Same goes for the other functions.

Thanks in advance.


Solution

  • How do I get if a socket is connected, bound, listening or closed from the socket/file descriptor passed as an argument.

    There is no single socket API to query a SOCKET's current state. However:

    • getsockname() will tell you whether the socket is bound locally or not.

    • getpeername() will tell you whether the socket is connected to a remote peer or not.

    • getsockopt() with the SOL_SOCKET:SO_ACCEPTCONN option will tell you whether a connection-oriented (ie, TCP) SOCKET is listen()'ing or not.

      Alternatively, if you try to connect() on a listen()'ing socket, you will get a WSAEINVAL error. If you try to listen() on a connect()'ed socket, you will get a WSAEISCONN error.

      Alternatively, if the socket is at least bound locally, then you can use getsockname() to get its local IP/port and then use GetTcpTable(), GetTcpTable2(), or GetExtendedTcpTable() to find out whether that IP/port is in a LISTENING state or not.

    • If a SOCKET has been closed locally, the SOCKET is not valid to begin with, so you can't query it for anything. The best thing you can do is just set the SOCKET to INVALID_SOCKET when you are done using it, and then check for that condition when needed. On the other hand, if the socket has been closed remotely but not locally yet, then the SOCKET is still valid, but there is no way to query its close state. The only way to know if the socket has been closed by the peer is if a recv() operation reports 0 bytes received, or if a send() operation fails with a connection error, or if you are using the SOCKET in asynchronous mode (WSAAsyncSelect() or WSAEventSelect()) and receive an FD_CLOSE notification for it.

    Note : I want to figure out the socket state without attempting to bind/connect/listen/closesocket because that will return a result and perform the operation. Example : if I wanted to check whether a socket is connected to a server I should attempt to connect and get the result which I don't want.

    Why are you not simply keeping track of the state in your own code? If you bind() a SOCKET and it succeeds, then you know it is bound locally. If you connect() and it succeeds, then you know it is bound locally and is connected to a remote server. You should maintain a state variable along-side your SOCKET variable, and keep the state updated with each state-changing operation you perform on the SOCKET.