Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# TCP套接字BeginReceive在收到少量消息后停止_C#_Sockets_Tcp - Fatal编程技术网

C# TCP套接字BeginReceive在收到少量消息后停止

C# TCP套接字BeginReceive在收到少量消息后停止,c#,sockets,tcp,C#,Sockets,Tcp,这是我的设想: 客户: 全天候连续发送xml数据(工作正常,不在我的控制范围内)。 服务器-我的代码: 1.不断地听。 2.接收传入消息,对其进行缓冲,并从缓冲区中创建有效的xml。 3.将其发送到MSMQ(主机将执行此操作) 我编写了一个tcp服务器代码(添加了来自google的代码片段),它将托管在windows服务中。当我在本地运行该服务时,一切正常,但当我将其置于PROD时,它会侦听多达73K条消息,并停止接收。它没有抛出任何异常。它只是在开始接收功能时阻塞。我也尝试过使用Receive

这是我的设想: 客户: 全天候连续发送xml数据(工作正常,不在我的控制范围内)。 服务器-我的代码: 1.不断地听。 2.接收传入消息,对其进行缓冲,并从缓冲区中创建有效的xml。 3.将其发送到MSMQ(主机将执行此操作)

我编写了一个tcp服务器代码(添加了来自google的代码片段),它将托管在windows服务中。当我在本地运行该服务时,一切正常,但当我将其置于PROD时,它会侦听多达73K条消息,并停止接收。它没有抛出任何异常。它只是在开始接收功能时阻塞。我也尝试过使用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()
    { }
}
StringBuilder内容=新建StringBuilder();
公共事件MessageReceiveEventHandler MessageReceived;
//ArrayList用于跟踪设计的工作套接字
//与每个连接的客户端通信。使其成为同步的ArrayList
//为了螺纹安全
private System.Collections.ArrayList workerSocketList=
Synchronized(new System.Collections.ArrayList());
private int m_clientCount=0;
私有套接字m_mainSocket=null;
私有异步回调ReadCallback;
私有异步回调连接回调;
public MedDeviceListener(字符串ipAddress,int-port,int-maxConnections=100)
{
ProfileProvider.Instance.LogInformationIf(_debug);
这个。_port=port;
这是。_ipAddress=ipAddress;
这是.\u maxConnections=maxConnections;
ReadCallback=新的异步回调(接收\处理程序);
ConnectionCallback=新的异步回调(连接\处理程序);
lenghtofStartMsg=标题。长度;
lengthOfEndMsg=footer.Length;
}
公开作废开始()
{
ProfileProvider.Instance.LogInformationIf(_debug);
//输入数据的数据缓冲区。
字节[]字节=新字节[_bufferSize];
//为套接字建立本地端点。
IPEndPoint localEndPoint=新的IPEndPoint(IPAddress.Parse(\u IPAddress),\u port);
//创建TCP/IP套接字。
m_mainSocket=新套接字(AddressFamily.InterNetwork,
流,ProtocolType.Tcp);
//将套接字绑定到本地端点并侦听传入连接。
尝试
{
m_mainSocket.Bind(localEndPoint);
m_mainSocket.监听(100);
InstrumentationProvider.Instance.LogInformation(“MedDeviceListener已成功连接到IP:+\u ipAddress+”\n端口:+\u端口);
m_mainSocket.beginacept(ConnectionCallback,m_mainSocket);
}
捕获(例外e)
{
InstrumentationProvider.Instance.LogException(“MedDeviceListener.Start”,e);
投掷e;
}
}
专用无效连接\u处理程序(IAsyncResult ar)
{
尝试
{
ProfileProvider.Instance.LogInformationIf(_debug);
套接字侦听器=(套接字)ar.AsyncState;
套接字workerSocket=listener.EndAccept(ar);
//现在增加此客户机的客户机计数
//以线程安全的方式
联锁。增量(参考m_客户端计数);
//将workerSocket引用添加到ArrayList
workerSocketList.Add(workerSocket);
SendConnectedAck(_clientConnectAckMessage,m_clientCount);
WaitForData(workerSocket,m_clientCount);
//恢复侦听回调循环
beginacept(连接处理程序,侦听器);
}
捕获(ObjectDisposedException)
{
InstrumentationProvider.Instance.LogInformation(“侦听器套接字已关闭”);
}
捕获(例外情况除外)
{
InstrumentationProvider.Instance.LogException(“连接处理程序”,ex);
投掷;
}
}
私有无效接收处理程序(IAsyncResult ar)
{
ProfileProvider.Instance.LogInformationIf(_debug);
StateObject状态=(StateObject)ar.AsyncState;
尝试
{
//检索状态对象和处理程序套接字
//从异步状态对象。
套接字工作组=state.workSocket;
//从客户端套接字读取数据。
int bytesRead=workSocket.EndReceive(ar);
如果(字节读取>0)
{
//InstrumentationProvider.Instance.LogInformationIf(_debug,bytesRead+“read..”);
//可能会有更多的数据,因此请解析到目前为止收到的数据。
字符串数据=Encoding.ASCII.GetString(state.buffer,0,bytesRead);
尝试
{
解析输入消息(数据、工作组);
}                        
catch(异常parsex)
{
content.Clear();
InstrumentationProvider.Instance.LogException(“ParseIncomingMessage”,parseEx);
}
}
WaitForData(state.workSocket、state.clientNumber);
}
捕获(ObjectDisposedException)
{
InstrumentationProvider.Instance.LogInformation(“接收处理程序:侦听器套接字已关闭”);
}
捕获(SocketException se)
{
//关闭现有连接
闭合插座();
//重新启动它
这个。Start();
}
}
私有void WaitForData(套接字workerSocket,int clientNumber)
{
ProfileProvider.Instance.LogInformationIf(_debug);
尝试
{
StateObject theSocPkt=新的StateObject(workerSocket,ClientNumber)