|
I ran into a few problems in the .NET socket implementation:
1) If you put a socket into non-blocking mode, you cannot retrieve the local and the remote endpoint. (The LocalEndpoint and RemoteEndpoint attributes are null when you read them.) To fix, you have to use platform invoke for getsockname() and getpeername(), which is messy.
2) Poll() blocks indefinitely if you pass a negative timeout (as it should). On the other hand, Select() silently treats a negative timeout the same as a zero timeout. The closest thing to a blocking Select() you can do is to pass IntMax. However, that gives you only about 5 and a half minutes, then the call times out. The work-around (restarting the select if it times out) is surprisingly complicated.
3) To set the receive or send timeout, you have to pass the timeout in milliseconds. However, Select() expects the timeout in microseconds. Not nice.
4) Reading from a non-blocking socket when no data is available doesn't return zero bytes but throws an exception instead. That's a royal pain: the exception that is thrown is SocketException, so there is no way to specifically handle timeouts. Instead, you have to get the underlying Win32 exception, read the error code, and see whether it is WSAEWOULDBLOCK. To boot, there are no definitions for the various error codes in the .NET framework, so you end up grepping through the Windows header files and have to put manifest constants into the code. And, of course, the whole design is broken because having to handle an exception for something that isn't an error condition makes a mess of the code.
5) I had some issues with non-blocking sockets and select -- on occasion, select would return a socket in the error set even though it shouldn't. I didn't follow up on exactly what caused this because it was easier to just reorganize my code, so I can't provide more detail.
Cheers,
Michi.
|