如何确保后续的BeginSend()没有两个?

时间:2013-03-14 11:13:47

标签: c# multithreading sockets synchronization asyncsocket

我编写了一个应该管理许多客户端的服务器端应用程序。一切都是使用BeginSend()和EndSend()方法异步完成的。

在某些情况下,我需要向其中一个客户端发送两个后续请求。我希望确保在第一个 BeginSend()和 last EndSend()之间没有调用新的BeginSend()。我虽然使用AutomaticResetEvent执行此操作,但如果服务器尝试向客户端发送两条消息,则第二条消息将阻塞,直到第一条消息被发送

  1. 这样做是否有意义?
  2. 代码中断有时会抛出“NullReferenceException”。我似乎无法理解为什么?
  3. 感谢您的见解。

    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;
            }
    
        }
    
    
    public void SendAsyncData(string str, CommandsToClient cmd)
            {
                byte[] data = Combine(BitConverter.GetBytes((int)(cmd)), BitConverter.GetBytes((int)(str.Length)), Encoding.ASCII.GetBytes(str));
                SendAutoResetEvent.WaitOne();
                SendAsyncDataWithHeader(data);
            }
    
    
            private void SendAsyncDataWithHeader(byte[] data)
            {
                int toSend;
                byte[] dataWithHeader = Combine(BitConverter.GetBytes(data.Length), data);
                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)
                {
    
                    Disconnected(this);
                }
    
            }
    
            void sendCallback(IAsyncResult ar)
            {
                try
                {
                    int bytesSent = socket.EndSend(ar);
                    if (bytesSent == 0)
                    {
                        if (Disconnected != null)
                        {
                            Disconnected(this);
                            return;
    
                        }
                    }
                    sendBuffer.sent += bytesSent;
                    if (sendBuffer.sent == sendBuffer.BUFFER.Length)
                    {
                        //all data was sent. do some
                        //do some processing...
                        sendBuffer.Dispose();
                        //let new send request in
                        SendAutoResetEvent.Set();
                        return;
                    }
                    int toSend;
                    // exception says that in the following line, sendBuffer.Buffer is null....
                    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 (NullReferenceException ex)
                {
                    //here an exception is thrown, 
                }
    
                catch (Exception ex)
                {
    
                    Disconnected(this);
                }
    
            }
    
        }
    }
    

0 个答案:

没有答案