Search code examples
c#socketsasynchronoussendasync

Why does SendAsync not raise the Completed Event on my SocketAsyncEventArgs even though my Server-Socket has already received all bytes?


So I am having a very simple setup: A Server that waits for a Client to connect and a Client who connects to the Server and sends messages. The Server should afterwards send the same message back again. But when I try to send the message with client.SendAsync(sendArgs) it doesn't actually call the Completed Event on the sendArgs object even though I can see that my Server-Socket has already received all the bytes. So why is sendArgs.Completed in my Client-Socket not being raised, but receiveArgs.Completed in my Server-Socket class?

Namespaces used: System, System.Net, System.Net,System.Text

This is my code so far:

Client

public class SocketClient
{
    public IPEndPoint Endpoint { get; }

    private Socket client;

    public SocketClient(IPAddress address, int port)
    {
        Endpoint = new IPEndPoint(address, port);
        client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    }

    public void ConnectToServer(IPAddress serverAddress, int serverPort)
    {
        client.Bind(Endpoint);

        try
        {
            client.Connect(serverAddress, serverPort);
        }
        catch (SocketException)
        {
            return;
        }
    }

    public void SendMessage(string message)
    {
        SocketAsyncEventArgs sendArgs = new SocketAsyncEventArgs();
        byte[] buffer = Encoding.ASCII.GetBytes(message);
        sendArgs.SetBuffer(buffer, 0, buffer.Length);
        sendArgs.Completed += SendArgs_Completed;
        client.SendAsync(sendArgs);
    }

    private void SendArgs_Completed(object sender, SocketAsyncEventArgs e)
    {
        SocketAsyncEventArgs receiveArgs = new SocketAsyncEventArgs();
        byte[] buffer = new byte[1024];
        receiveArgs.SetBuffer(buffer, 0, buffer.Length);
        receiveArgs.Completed += ReceiveArgs_Completed;
        client.ReceiveAsync(receiveArgs);
    }

    private void ReceiveArgs_Completed(object sender, SocketAsyncEventArgs e)
    {
        string message = Encoding.ASCII.GetString(e.Buffer);
        Console.WriteLine(message);
    }
}

Server

public class SocketServer
{
    public IPEndPoint Endpoint { get; }

    private Socket server;

    public SocketServer(IPAddress address, int port)
    {
        Endpoint = new IPEndPoint(address, port);
        server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    }

    public void Start()
    {
        server.Bind(Endpoint);
        server.Listen(10);

        SocketAsyncEventArgs acceptArgs = new SocketAsyncEventArgs();
        acceptArgs.Completed += AcceptArgs_Completed;
        server.AcceptAsync(acceptArgs);
    }

    private void AcceptArgs_Completed(object sender, SocketAsyncEventArgs e)
    {
        Socket connectionSocket = e.AcceptSocket;

        SocketAsyncEventArgs receiveArgs = new SocketAsyncEventArgs();
        byte[] buffer = new byte[1024];
        receiveArgs.SetBuffer(buffer, 0, buffer.Length);
        receiveArgs.Completed += ReceiveArgs_Completed;
        connectionSocket.ReceiveAsync(receiveArgs);

        e.AcceptSocket = null;
        server.AcceptAsync(e);
    }

    private void ReceiveArgs_Completed(object sender, SocketAsyncEventArgs e)
    {
        Socket connectionSocket = (Socket)sender;

        SocketAsyncEventArgs sendArgs = new SocketAsyncEventArgs();
        sendArgs.SetBuffer(e.Buffer, 0, e.Buffer.Length);
        connectionSocket.SendAsync(sendArgs);

        connectionSocket.ReceiveAsync(e);
    }
}

Solution

  • Edit: I fixed it. The thing I was missing was to check if the SendAsync method has finished synchronously or asynchronously. If it finishes synchronously I need to call the event myself

    bool completedAsync = client.SendAsync(sendArgs);
    if(!completedAsync)
    {
        SendArgs_Completed(this, sendArgs);
    }