Cross-platform, the only way is to perform an I/O operation on the socket and check for error. On Windows, at least, a non-blocking socket can issue an asynchronous FD_CLOSE notification when the connection is closed, but you should still check I/O operations for errors, too.
The same type of coding will work on POSIX, too. The base BSD socket API, like select() and recv(), is common across multiple platforms.
Why are you passing your fd_set variable as the buffer for recv() to read into? More importantly, you can't pass -1 as the size of the buffer to read into. On Windows, the len parameter is an int, so it will at least compile with a length of -1, but semantically asking recv() to read -1 number of bytes makes no sense, and is not documented as a supported operation. But worse, on other platforms, the len parameter is a size_t, which is an unsigned type, so passing in a length of -1 will wrap to a very large value and very bad things can happen!
Also, you are not checking to make sure that select() actually reports the socket is readable before then calling recv() on the socket. Since you are only querying 1 socket, the return value of select() will be -1 on error, 0 on timeout (not readable), and 1 (readable). Alternatively, since select() modifies the fd_set struct on output, you can check if your socket is still in the set after select() exits.
Also, you are not handling recv() reporting an error at all.
Either way, do keep in mind that you are performing an actual read, so any bytes that recv() does actually receive will not be available for subsequent reads, so you will have to buffer the bytes somewhere in memory so you can still use them later.
In most cases, implementing an IsConnected() type of function is really unnecessary and should be avoided.