0

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

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

  1. 以上述方式这样做有意义吗?
  2. 代码有时会抛出“NullReferenceException”。我似乎无法理解为什么?

感谢您的见解。

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);
            }

        }

    }
}
4

0 回答 0