TCP Socket BeginReceive在收到几条消息后停止

时间:2014-08-26 20:53:07

标签: c# sockets tcp

这是我的情景: 客户:  连续24/7连续发送xml数据 - (它工作正常,不在我的控制之下)。 服务器 - 我的代码:    1.不断听。    2.接收传入消息,缓冲它并从缓冲区创建有效的xml。    3.将其发送到MSMQ(主机将执行此操作)

我写了一个tcp服务器代码(从谷歌添加代码片段),它将在Windows服务中托管。当我在本地运行服务时,一切正常,但是当我将它放置PROD时,它会监听多达73K的消息,并且它会停止接收。它没有抛出任何异常。它只是阻止 BeginReceive 功能。我也尝试过使用ReceiveTimeOut。我也见过netstat,连接仍然是已建立的统计数据。 当我重新启动服务时,它再次正常工作。我在这里发布我的服务器代码。请帮忙。

    StringBuilder content = new StringBuilder();
    public event MessageReceiveEventHandler MessageReceived;

    // An ArrayList is used to keep track of worker sockets that are designed
    // to communicate with each connected client. Make it a synchronized ArrayList
    // For thread safety
    private System.Collections.ArrayList workerSocketList =
            ArrayList.Synchronized(new System.Collections.ArrayList());

    private int m_clientCount = 0;
    private Socket m_mainSocket = null;

    private AsyncCallback ReadCallback;
    private AsyncCallback ConnectionCallback;
    public MedDeviceListener(string ipAddress, int port, int maxConnections=100)
    {
        ProfileProvider.Instance.LogInformationIf(_debug);
        this._port = port;
        this._ipAddress = ipAddress;
        this._maxConnections = maxConnections;
        ReadCallback = new AsyncCallback(Receive_handler);
        ConnectionCallback = new AsyncCallback(Connection_handler); 
        lenghtofStartMsg = header.Length;
        lengthOfEndMsg = footer.Length;
    }

    public void Start()
    {
        ProfileProvider.Instance.LogInformationIf(_debug);
        // Data buffer for incoming data.
        byte[] bytes = new Byte[_bufferSize];

        // Establish the local endpoint for the socket.       

        IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Parse(_ipAddress), _port);

        // Create a TCP/IP socket.
        m_mainSocket = new Socket(AddressFamily.InterNetwork,
            SocketType.Stream, ProtocolType.Tcp);

        // Bind the socket to the local endpoint and listen for incoming connections.
        try
        {
            m_mainSocket.Bind(localEndPoint);
            m_mainSocket.Listen(100);
            InstrumentationProvider.Instance.LogInformation("MedDeviceListener successfully connected to IP:" + _ipAddress+"\nPort :"+_port);
            m_mainSocket.BeginAccept(ConnectionCallback, m_mainSocket);                
        }
        catch (Exception e)
        {
            InstrumentationProvider.Instance.LogException("MedDeviceListener.Start", e);
            throw e;
        }
    }

    private void Connection_handler(IAsyncResult ar)
    {
        try
        {
            ProfileProvider.Instance.LogInformationIf(_debug);
                Socket listener = (Socket)ar.AsyncState;

                Socket workerSocket = listener.EndAccept(ar);
                // Now increment the client count for this client 
                // in a thread safe manner
                Interlocked.Increment(ref m_clientCount);

                // Add the workerSocket reference to our ArrayList
                workerSocketList.Add(workerSocket);
                SendConnectedAck(_clientConnectAckMessage, m_clientCount);
                WaitForData(workerSocket, m_clientCount);
                //Resume the listening callback loop
                listener.BeginAccept(Connection_handler, listener);
        }
        catch (ObjectDisposedException)
        {
            InstrumentationProvider.Instance.LogInformation("The listener socket has been closed");
        }
        catch (Exception ex)
        {
            InstrumentationProvider.Instance.LogException("Connection_handler", ex);
            throw;
        }
    }
    private void Receive_handler(IAsyncResult ar)
    {
        ProfileProvider.Instance.LogInformationIf(_debug);
        StateObject state = (StateObject)ar.AsyncState;
        try
        {
            // Retrieve the state object and the handler socket
            // from the asynchronous state object.
            Socket workSocket = state.workSocket;

            // Read data from the client socket. 
            int bytesRead = workSocket.EndReceive(ar);

            if (bytesRead > 0)
            {
                //InstrumentationProvider.Instance.LogInformationIf(_debug, bytesRead+" read..");
                // There  might be more data, so parse the data received so far.
                string data= Encoding.ASCII.GetString(state.buffer, 0, bytesRead);
                try
                {
                    ParseIncomingMessage(data, workSocket);
                }                        
                catch(Exception parseEx)
                {
                    content.Clear();
                    InstrumentationProvider.Instance.LogException("ParseIncomingMessage", parseEx);
                }
            }
            WaitForData(state.workSocket, state.clientNumber);
        }
        catch (ObjectDisposedException)
        {
            InstrumentationProvider.Instance.LogInformation("Receive_handler: The listener socket has been closed");
        }
        catch (SocketException se)
        {
            //close the existing connection
            CloseSockets();
            //restart it again
            this.Start();
        }
    }
    private void WaitForData(Socket workerSocket, int clientNumber)
    {
        ProfileProvider.Instance.LogInformationIf(_debug);
        try
        {
            StateObject theSocPkt = new StateObject(workerSocket, clientNumber);
            workerSocket.ReceiveTimeout = 2000;
            workerSocket.BeginReceive(theSocPkt.buffer, 0,
                theSocPkt.buffer.Length,
                SocketFlags.None,
                Receive_handler,
                theSocPkt);
        }
        catch(TimeoutException ex)
        {
            InstrumentationProvider.Instance.LogException("WaitForData - TimeOutException", ex);
        }
        catch (SocketException se)
        {
            InstrumentationProvider.Instance.LogException("MedDeviceListener.WaitForData", se);
            //close the existing connection
            CloseSockets();
            //restart it again
            this.Start();
        }
        catch (Exception ex)
        {
            InstrumentationProvider.Instance.LogException("WaitForData",ex);
            //close the existing connection
            CloseSockets();
            //restart it again
            this.Start();
        }
    }
    private void ParseIncomingMessage(string msg,Socket wrkSocket)
    {
        Socket workSocket = wrkSocket;
        bool hasStartTag = isMsgContainsStartTag(msg);
        bool hasEndTag = isMsgContainsEndTag(msg);
        int startTagIndex = indexOfStartTag(msg);
        int endTagIndex = indexOfEndTag(msg);
        // If the incomming message dont have either start or end tag
        if (hasStartTag == false && hasEndTag == false)
        {
            content.Append(msg);
        }
        //check for the starttag first
        //if message contains startTag
        else if (hasStartTag)
        {
            if (startTagIndex != 0)//there is something before starttag
            {
                string subStr = msg.Substring(0, startTagIndex);
                content.Append(subStr);
                //Check and send the content
                CheckSendMessage(workSocket);
                //Parse the remaining message from start tag to end of the message
                ParseIncomingMessage(msg.Substring(startTagIndex, msg.Length - subStr.Length), wrkSocket);
            }
            else if (startTagIndex == 0)
            {
                content.Clear();
                if (hasEndTag)
                {
                    int endOfEndTag = endTagIndex + lengthOfEndMsg;
                    string subStr = msg.Substring(0, endOfEndTag); //message statrs with start tag and ends contains full end tag so first get that string and send that.
                    content.Append(subStr);
                    CheckSendMessage(workSocket);
                    //Parse the remaining message from endtag+1 to end
                    ParseIncomingMessage(msg.Substring(endOfEndTag, msg.Length - endOfEndTag), wrkSocket);
                }
                else
                {
                    content.Append(msg);
                }
            }
        }
        //if message contains EndTag ALONE
        else if (hasEndTag)
        {
            int endOfEndTag = endTagIndex + lengthOfEndMsg;
            string subStr = msg.Substring(0, endOfEndTag);
            content.Append(subStr);
            CheckSendMessage(workSocket);
            //Parse remaining message after end tag
            ParseIncomingMessage(msg.Substring(endOfEndTag, msg.Length - endOfEndTag), wrkSocket);
        }
    }
    private void CheckSendMessage(Socket workSocket)
    {
        string msg=content.ToString().Trim();
        //if content contains both start and end tag then send the content
        if (isMsgContainsStartTag(msg) && isMsgContainsEndTag(msg) &&
            indexOfStartTag(msg) == 0 && indexOfEndTag(msg) + lengthOfEndMsg == msg.Length)
        {
            //Send the message
            using (MedDeviceListenerEventArgs e = new MedDeviceListenerEventArgs(msg))
            {
                OnReceiveComplete(e);
                SendReceiveAck(workSocket, _receiveAckMessage);
            }
        }
    }
    private void SendReceiveAck(Socket handler, String data)
    {
        try
        {
            ProfileProvider.Instance.LogInformationIf(_debug);
            // Convert the string data to byte data using ASCII encoding.
            byte[] byteData = Encoding.ASCII.GetBytes(data);
            handler.Send(byteData);
            InstrumentationProvider.Instance.LogInformationIf(_debug, "Message received acknowledgement:" + _receiveAckMessage + " has been sent successfully");
        }
        catch (Exception ex)
        {
            InstrumentationProvider.Instance.LogException("SendReceiveAck", ex);                
        }
    }
    private void SendConnectedAck(string msg, int clientNumber)
    {
        ProfileProvider.Instance.LogInformationIf(_debug);
        try
        {
            // Convert the reply to byte array
            byte[] byData = System.Text.Encoding.ASCII.GetBytes(msg);

            Socket workerSocket = (Socket)workerSocketList[clientNumber - 1];
            workerSocket.Send(byData);
            InstrumentationProvider.Instance.LogInformationIf(_debug, "Client Connected acknowledgement:" + _clientConnectAckMessage + " has been sent successfully");
        }
        catch (Exception ex)
        {
            InstrumentationProvider.Instance.LogException("SendConnectedAck", ex);
            throw;
        }
    }
    public void CloseSockets()
    {
        try
        {
            ProfileProvider.Instance.LogInformationIf(_debug);
            if (m_mainSocket != null)
            {
                if (m_mainSocket.Connected)
                {
                    m_mainSocket.Shutdown(SocketShutdown.Both);
                    m_mainSocket.Close();
                    m_mainSocket = null;
                }
            }
            Socket workerSocket = null;
            for (int i = 0; i < workerSocketList.Count; i++)
            {
                workerSocket = (Socket)workerSocketList[i];
                if (workerSocket != null)
                {
                    workerSocket.Shutdown(SocketShutdown.Both);
                    workerSocket.Close();
                    workerSocket = null;
                }
            }
        }
        catch(Exception ex) 
        {
            InstrumentationProvider.Instance.LogException("CloseSockets",ex);
        }
    }

    protected virtual void OnReceiveComplete(MedDeviceListenerEventArgs e)
    {
        if (MessageReceived != null)
        {
            MessageReceived(this, e);
        }
    }

    private int indexOfStartTag(string msg)
    {
        return msg.IndexOf(header);
    }
    private int indexOfEndTag(string msg)
    {
        return msg.IndexOf(footer);
    }
    private bool isMsgContainsStartTag(string msg)
    {
        return msg.Contains(header);
    }
    private bool isMsgContainsEndTag(string msg)
    {
        return msg.Contains(footer);
    }


public delegate void MessageReceiveEventHandler(object sender,MedDeviceListenerEventArgs e);

public class MedDeviceListenerEventArgs : EventArgs,IDisposable
{
    private string _receivedData;
    public MedDeviceListenerEventArgs(string receivedData)
    {
        _receivedData = receivedData;
    }
    public string ReceivedData
    {
        get
        {
            return _receivedData;
        }
    }

    public void Dispose()
    { }
}

}

我看过类似的帖子,尝试了一切,但没有运气。请帮助:)

由于 -MM

0 个答案:

没有答案