0

I've written a serverside application that manages many clients using BeginSend() and EndSend()

I'm struggling for the past hours to make sure no consequent BeginSend() calls are called for the same client.

It seems that the following code snippet doesn't achieve my goal and doesn't block on the second call to SendAsyncData before the first completed.

What is my mistake?

struct SendBuffer
{
    public const int BUFFER_SIZE = 1024 * 128;
    public byte[] BUFFER;
    public int sent;

    public SendBuffer(byte[] data)
    {
        BUFFER = new byte[data.Length];
        Buffer.BlockCopy(data, 0, BUFFER, 0, data.Length);
        sent = 0;
    }

    public void Dispose()
    {
        BUFFER = null;
        sent = 0;
    }
}

private void SendAsyncDataWithHeader(byte[] data
{
    int toSend;
    byte[] dataWithHeader = Combine(BitConverter.GetBytes(data.Length), data);

    SendAutoResetEvent.WaitOne();
    sendBuffer = new SendBuffer(dataWithHeader);

    if (sendBuffer.BUFFER.Length - sendBuffer.sent > SendBuffer.BUFFER_SIZE)
        toSend = SendBuffer.BUFFER_SIZE;
    else
        toSend = sendBuffer.BUFFER.Length - sendBuffer.sent;

    try
    {
        socket.BeginSend(sendBuffer.BUFFER, 0, toSend, SocketFlags.None, sendCallback, null);
    }
    catch (SocketException se)
    {
        switch (se.SocketErrorCode)
        {
            case SocketError.ConnectionAborted:
            case SocketError.ConnectionReset:
                if (Disconnected != null)
                {
                    Disconnected(this);
                }
                break;
        }
    }
    catch (ObjectDisposedException)
    {
    }
    catch (NullReferenceException ex)
    {
    }
    catch (Exception ex)
    {
        Server.logger.Error(ex);
        Disconnected(this);
    }
}

void sendCallback(IAsyncResult ar)
{
    int bytesSent;
    try
    {
        bytesSent = socket.EndSend(ar);
        if (bytesSent == 0)
        {
            if (Disconnected != null)
            {
                Disconnected(this);
                return;
            }
        }
        sendBuffer.sent += bytesSent;
        if (sendBuffer.sent == sendBuffer.BUFFER.Length)
        {
            sendBuffer.Dispose();

            SendAutoResetEvent.Set();
            Server.logger.Info("set {0}", userName);
        }
        else
        {
            int toSend;
            if (sendBuffer.BUFFER.Length - sendBuffer.sent > SendBuffer.BUFFER_SIZE)
                toSend = SendBuffer.BUFFER_SIZE;
            else
                toSend = sendBuffer.BUFFER.Length - sendBuffer.sent;

            socket.BeginSend(sendBuffer.BUFFER, sendBuffer.sent, toSend, SocketFlags.None, sendCallback, null);
        }
    }
    catch (SocketException se)
    {
        switch (se.SocketErrorCode)
        {
            case SocketError.ConnectionAborted:
            case SocketError.ConnectionReset:
                if (Disconnected != null)
                {
                    Disconnected(this);
                    return;
                }
                break;
        }
    }
    catch (ObjectDisposedException ex)
    {
    }
    catch (Exception ex)
    {
        Server.logger.Error(ex);
        Disconnected(this);
    }
}
Iridium
  • 23,323
  • 6
  • 52
  • 74
Daniel
  • 1,319
  • 14
  • 19
  • 2
    What is in the catch/finally of the two try blocks? You seem to have omitted them. – Iridium Mar 14 '13 at 18:58
  • How do you run any code in a class with all private methods? – Peter Ritchie Mar 14 '13 at 19:07
  • @PeterRitchie static void Main()? ;) – Asik Mar 14 '13 at 19:08
  • @Dr_Asik yeah, but this isn't the `Program` class and there is no `Main` – Peter Ritchie Mar 14 '13 at 19:11
  • I didn't post it because it felt irrelevant. Maybe I'm wrong? I only use a catch block, with SocketException and ObjectDisposed. SocketException disposes the socket. ObjectDisposed does nothing – Daniel Mar 14 '13 at 19:12
  • It would help a lot if you showed where `SendAsyncData` was being called in your application. – Joel Daignault Mar 14 '13 at 19:13
  • I've updated to the (almost) full version... – Daniel Mar 14 '13 at 19:19
  • 2
    Please post a short, compilable, but complete, example that reproduces the problem – Peter Ritchie Mar 14 '13 at 19:36
  • Assuming that each socket has a separate `AutoResetEvent`, there doesn't appear any reason for multiple threads to be released unless there's something else that you've omitted in your question that is causing it. How are you determining that multiple threads are being released, and what steps have you taken to debug the issue? – Iridium Mar 14 '13 at 22:26

0 Answers0