Behavioral differences between the CF and FFx

One of the things we tend to take for granted and assume to be true is that identical code will produce identical behaviors across different platforms.  It only seems sensible that if we write some C# code that compiles and runs for the full framework as well as the compact framework that the resulting behavior, provided the code isn’t obviously platform dependent, should behave the same.  Right?

Apparently not.

While porting some networking code today from the device to the desktop, I was having failures in code that I was certain worked.  It turns out that sockets don’t behave the same.  Since a Socket class is an abstraction of something that is pretty damned standard, the fact that we have this disparity surprises and alarms me.  It smells an awful lot like a bug.

Want to try it yourself?  I put together some pretty basic repro code:

class Program

{

private Socket m_serverSocket;

private ManualResetEvent m_requestDoneEvent = new ManualResetEvent(false);

public static void Main()

{

Program p = new Program();

p.Run();

}

public void Run()

{

IPEndPoint localEndpoint = new IPEndPoint(IPAddress.Any, 90);

m_serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

m_serverSocket.Bind(localEndpoint);

Thread serverThread = new Thread(ServerThreadProc);

serverThread.IsBackground = true;

serverThread.Priority = ThreadPriority.AboveNormal;

serverThread.Start();

Thread.Sleep(100);

Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

EndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 90);

clientSocket.Connect(ep);

m_requestDoneEvent.WaitOne(10000, false);

}

private void ServerThreadProc()

{

m_serverSocket.Listen(10);

m_requestDoneEvent.Reset();

m_serverSocket.BeginAccept(AcceptRequest, m_serverSocket);

// wait for the async accept to complete

m_requestDoneEvent.WaitOne(10000, false);

}

private void AcceptRequest(IAsyncResult result)

{

Debug.WriteLine("rnn -------------------------------------------");

Debug.WriteLine("| The current Platform is " + Environment.OSVersion.Platform.ToString());

Debug.WriteLine("| The server socket reports Connected == " + m_serverSocket.Connected.ToString());

Debug.WriteLine(" -------------------------------------------rnn");

m_requestDoneEvent.Set();

}

}


And the outputs:

On the desktop:

 -------------------------------------------
|  The current Platform is Win32NT
|  The server socket reports Connected == False
 -------------------------------------------

On the device:

 -------------------------------------------
|  The current Platform is WinCE
|  The server socket reports Connected == True
 -------------------------------------------

WTF?!


	

6 thoughts on “Behavioral differences between the CF and FFx”

  1. Something is very wrong here!

    How can the Socket on WinCE report connected when you haven’t called EndAccept to actually accept the pending connection?!

    I tried your code with AcceptRequest modified to the following:

    private void AcceptRequest(IAsyncResult result)
    {

    Debug.WriteLine("rnn ——————————————-");

    Debug.WriteLine("| The current Platform is " + Environment.OSVersion.Platform.ToString());

    Debug.WriteLine("| The server socket reports Connected == " + m_serverSocket.Connected.ToString());

    Socket s = ((Socket)result.AsyncState).EndAccept(result);

    Debug.WriteLine("| The s socket reports Connected == " + s.Connected.ToString());

    Debug.WriteLine(" ——————————————-rnn");

    m_requestDoneEvent.Set();

    }

    And got the following results:

    ——————————————-
    | The current Platform is Win32NT
    | The server socket reports Connected == False
    | The s socket reports Connected == True
    ——————————————-

    ——————————————-
    | The current Platform is WinCE
    | The server socket reports Connected == True
    | The s socket reports Connected == True
    ——————————————-

    The Win32NT result makes sense but the WinCE result really looks like a bug to me.

    Regards,
    Frank.

    Like

  2. It is obviously not relevant to test if a listening socket is connected…
    You should only test clientSocket or the socket resulting from Accept (of EndAccept in this asynchronous scenario).
    However I agree we should have the same behavior with both platforms even if this is not really a problem in this case.

    Like

  3. Hi

    1.) Inserting new records on my PDA Windows Mobile Operating System 6.0
    2.) I do a Full Sync on the PDA.
    3.) A Date Time error happens on these records
    (due to new Daylight Savings Time enacted in 2007).

    Does anyone know of a DST (daylight savings time) Patch for the PDA 6.0 Windows
    Operating System or where I can get this on the Microsoft site?

    Thanks!
    Dan

    Like

  4. I observed the same socket behavior in CF 2.0 using BeginConnect also. No matter what the state of the connection, the socket.Connected state was always true.

    I believe that I solved the problem by attempting to write a zero length byte array to the socket. After this write, the socket.Connected state was correct.

    private void EndConnect(IAsyncResult iar)
    {
    try
    {

    Socket socket = (Socket)iar.AsyncState;
    socket.EndConnect(iar);

    socket.Send(new byte[0]);

    }
    catch (SocketException se)
    {
    try
    {
    if (_theSocket != null)_theSocket.Close();
    }
    catch { }
    }
    catch (Exception e)
    {
    try
    {
    if (_theSocket != null)_theSocket.Close();
    }
    catch { }
    }
    }

    Like

  5. I observed the same socket behavior in CF 2.0 using BeginConnect also. No matter what the state of the connection, the socket.Connected state was always true.

    I believe that I solved the problem by attempting to write a zero length byte array to the socket. After this write, the socket.Connected state was correct.

    private void EndConnect(IAsyncResult iar)
    {
    try
    {

    Socket socket = (Socket)iar.AsyncState;
    socket.EndConnect(iar);

    socket.Send(new byte[0]);

    }
    catch (SocketException se)
    {
    try
    {
    if (_theSocket != null)_theSocket.Close();
    }
    catch { }
    }
    catch (Exception e)
    {
    try
    {
    if (_theSocket != null)_theSocket.Close();
    }
    catch { }
    }
    }

    Like

  6. Its a common misconception that the Connected property returns the state of the underlying socket. It doesn’t, it returns true or false based upon the last operation performed on the socket.

    Consider this:

    Open a socket, Connected is true
    Send some data, Connected is true
    Close the remote end, Connected still is true
    Send some data, a SocketException is thrown, Connected now returns false.

    There are several bugs submitted to Microsoft about the confusing behaviour of the Connected and Available properties.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s