Search code examples
c#linuxsocketsasynchronousoverlapped-io

Linux Overlapped I/O TCP socket server not responsing to C# ASync Client correctly


I am trying to code a simple functioning echo socket client/server. I have managed to get a Synchronous server with a client to work, but now I need an asynchronous.

If I use Microsofts versions it is functioning good, ASync Server:

https://msdn.microsoft.com/en-us/library/fx6588te(v=vs.110).aspx

Microsoft ASync Client:

https://msdn.microsoft.com/en-us/library/bew39x2a(v=vs.110).aspx

What I am trying now is to get Microsoft Async Client communicate with a Linux C++ Overlapped I/O Server:

http://www.tutorialized.com/tutorial/Linux-C-Overlapped-Server-and-Client-Socket-Example/77220

Here the problems begin. The connection is established and I can send a message to the Server, the server responds echoing back the message (according to debug and terminal output) but the Microsoft ASync Client never gets the response on its socket.

Is it impossible to connect an ASync Client to an Overlapped I/O server? I am not sure why the reply from the server never reaches the client. Debugging the Microsoft ASync Client tells me that the Receive function never get passed this line of code:

receiveDone.WaitOne();

receiveDone is a ManualResetEvent:

private static ManualResetEvent receiveDone =
            new ManualResetEvent(false);

Context:

// Receive the response from the remote device.
Receive(client);
receiveDone.WaitOne();

Here is the callback function for receiving, setting the receiveDone when done. bytesRead never exceeds 0.:

private void ReceiveCallback(IAsyncResult ar)
{
    try
    {
        // Retrieve the state object and the client socket 
        // from the asynchronous state object.
        StateObject state = (StateObject)ar.AsyncState;
        Socket client = state.workSocket;

        // Read data from the remote device.
        int bytesRead = client.EndReceive(ar);

        if (bytesRead > 0)
        {
            // There might be more data, so store the data received so far.
            state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));

            // Get the rest of the data.
            client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
                new AsyncCallback(ReceiveCallback), state);
        }
        else
        {
            // All the data has arrived; put it in response.
            if (state.sb.Length > 1)
            {
                response = state.sb.ToString();
            }
            // Signal that all bytes have been received.
            receiveDone.Set();
        }
    }
    catch (Exception e)
    {
        msg("Fail ReceiveCallback: " + e.Message, false);
    }
} 

Anyway, this code is working when connected to an ASync Server, but not the Overlapped I/O server, so actually I am asking for what to change in the Overlapped I/O server code, for it to send back messages that the ASync Client can receive?

This is the output from the server if sent Hello World from the ASync Client:

root@deb7sve:/home/petlar/Host/SockServer# g++ OverlappedServer.cpp -o os.out -lpthread
root@deb7sve:/home/petlar/Host/SockServer# ./os.out
---------------------
Received connection from 10.0.2.2
Read 13 bytes from 4
Sent 13 bytes to 4

Solution

  • That client code only sets the event when the connection is shut down. According to your comment the server does not close the connection. That's why the event is never set.

    Throw the client code away and rewrite it using simple synchronous code. 50% of your code is devoted to making async IO (in a broken way). Async IO is not about improving network efficiency. It's there to save thread resources. Chances are it's not needed on the client.