Why do I get SocketExceptions on NetCF when setting some socket options?

I am frequently asked why NetCF applications encounter a SocketException when attempting to use some socket options, when applications written to the full .NET Framework do not. The companion question is invariably "Is this a bug in NetCF?".

If the result is WSAENOPROTOOPT (10042), what we are seeing is limitations of the operating system -- in this case, Windows CE -- so the answer is “no, this is not a bug, it is a limiation of the underlying operating system.“

Since the beginning, the .NET Compact Framework was designed to be portable -- run on more than one operating system. Because of this, we did not limit the available options in the SocketOptionNames enum. When calling Socket.GetSocketOption() or Socket.SetSocketOption(), the request is forwarded on to the operating system to do the work. If the result is a failure, the return code is wrapped into a SocketException and thrown.

The list of socket options which you can expect to throw, as described above, can be seen below (taken from the Windows CE API reference).

GetSocketOption
BSD options not supported for getsockopt are as follows.

Value Type Description
SO_RCVLOWAT int Retrieves recv low watermark.
SO_RCVTIMEO int Retrieves recv time-out value.
SO_SNDLOWAT int Retrieves send low watermark.
SO_SNDTIMEO int Retrieves time-out value for send.
TCP_MAXSEG int RetrievesTCP maximum-segment size.

Note: The above table taken from the MSDN documentation for getsockopt .

SetSocketOption
The following table shows BSD options not supported for setsockopt .

Value Type Description
SO_ACCEPTCONN BOOL Sets socket listening.
SO_RCVLOWAT int Sets recv low watermark.
SO_RCVTIMEO int Sets time-out for recv.
SO_SNDLOWAT int Sets send low watermark.
SO_SNDTIMEO int Sets time-out value for send.
SO_TYPE Int Sets socket type.

Note: The above table taken from the MSDN documentation for setsockopt .

If you are writing portable code (runs on both the .NET Framework and the .NET Compact Framework), you will need to handle this exception and change your application behavior as needed. For example, you may wish to disable controls related to expert socket features (ex: Receive Timeout). The code fragment below shows

using System.Net;
using System.Net.Sockets;

class SocketHelpers
{
bool ReceiveTimeoutSupported(Socket socket)
{
try
{
// try to get ReceiveTimeout option (this will get the default value)
Int32 timeout = (Int32)socket.GetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReceiveTimeout);

         // try to set what we received (we don't want to change the default value)
socket.SetSocketOption(SocketOptionLevel.Socket,
SocketOptionName.ReceiveTimeout,
timeout);

         // if we get here, ReceiveTimeout is supported
return true;
}
catch(SocketException e)
{
// check to see if the selected option is supported
if(10042 != e.ErrorCode) // WSAENOPROTOOPT
{
// ReceiveTimeout not supported by operating system
return false;
}
else
{
// no, let the caller handle the exception
throw;
}
}
}
}

I hope this helps clear up some of the confusion around socket options and the .Net Compact Framework.

-- DK

Disclaimer:
This posting is provided "AS IS" with no warranties, and confers no rights.