C#TCP侦听器在发生错误后停止

时间:2014-07-31 18:16:00

标签: c# tcp tcplistener

我有一个监听tcp端口的Windows服务,并在获取任何数据包时执行一些操作(com端口)。我使用的是来自http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener(v=vs.110).aspx网址。

代码工作正常,但是如果在第二个while循环内发生任何错误,则进程/ WhileLoop会停止(错误在try catch块中分别在第二个while循环内处理)。

我希望服务能够继续监听/处理下一个数据包,即使在上一次处理导致错误之后也是如此。

    protected override void OnStart(string[] args)
    {
        try
        {
            Thread _thread = new Thread(DoTask);
            _thread.Name = Utility.THREAD_NAME;
            _thread.IsBackground = true;
            _thread.Start();
        }
        catch (Exception ex)
        {
            Utility.WriteLog("Error Occurred in Service Start: OnStart():" + ex.Message);
        }

    }

    protected override void OnStop()
    {
        // TODO: Add code here to perform any tear-down necessary to stop your service.
    }

    protected void DoTask()
    {
        TcpListener server=null;   
        try
        {
            // Set the TcpListener on port 13000.
            Int32 port = 8002;
            IPAddress localAddr = IPAddress.Any;

            // TcpListener server = new TcpListener(port);
            server = new TcpListener(localAddr, port);

            // Start listening for client requests.
            server.Start();

            // Buffer for reading data
            Byte[] bytes = new Byte[256];
            String data = null;

            // Enter the listening loop. 
            while(true) 
            {
                Utility.WriteLog("Waiting for a connection... ");

                // Perform a blocking call to accept requests.
                // You could also user server.AcceptSocket() here.
                TcpClient client = server.AcceptTcpClient();
                Utility.WriteLog("Connected!");

                data = null;

                // Get a stream object for reading and writing
                NetworkStream networkStream = client.GetStream();

                int i;

                // Loop to receive all the data sent by the client. 
                while((i = networkStream.Read(bytes, 0, bytes.Length))!=0) 
                {

                    //System.Diagnostics.Debugger.Launch();

                    // Translate data bytes to a ASCII string.
                    data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);                        
                    Utility.WriteLog("Received: " + data);

                    string CartCommand = data;

                    #region PROCESSING AT COMMAND AT FIRMWARE

                    try
                    {
                        string SerialResponse = string.Empty;
                        CreateSerialPort();
                        if (_serialPort.IsOpen == false)
                        {
                            _serialPort.Open();
                        }

                        _serialPort.Write(CartCommand); /* Execute Network Supplied Command to Serial Port */
                        Thread.Sleep(_ResponseWait);

                        byte[] SPResponsebyte = new byte[_serialPort.ReadBufferSize];
                        int intSPtBytes = _serialPort.Read(SPResponsebyte, 0, SPResponsebyte.Length); /* Read the Serial Port Response after Command Execution */
                        SerialResponse = System.Text.Encoding.ASCII.GetString(SPResponsebyte, 0, intSPtBytes);

                        SPResponsebyte = System.Text.Encoding.ASCII.GetBytes(SerialResponse);
                        networkStream.Write(SPResponsebyte, 0, SPResponsebyte.Length);

                        Utility.WriteLog(SerialResponse);
                    }
                    catch (Exception ex)
                    {
                        Utility.WriteLog("Error: " + ex.Message);
                        // This is the problem area, the while loop don't accept next commands after this.
                    }
                    finally
                    {
                        if (_serialPort.IsOpen == true)
                        {
                            _serialPort.Close();
                        }
                    }

                    #endregion

                    // Send back a response.
                    //stream.Write(msg, 0, msg.Length);
                    //Utility.WriteLog("Sent: " + data);
                }

                // Shutdown and end connection
                client.Close();
            }
        }
        catch(SocketException e)
        {                
            Utility.WriteLog("SocketException: " + e);
        }            
        finally
        {
            // Stop listening for new clients.
            server.Stop();
            Utility.WriteLog("Stop listening.");
        }

        Utility.WriteLog("Cycle complete.");

      }

    private bool CreateSerialPort()
    {
        try
        {

            _configDoc = new ConfigDoc();

            if (_configDoc != null)
            {
                _serialPort = new SerialPort();
                _serialPort.PortName = _configDoc.PortName;
                _serialPort.BaudRate = Convert.ToInt32(_configDoc.BaudRate);
                _serialPort.Parity = _configDoc.ParityBit;
                _serialPort.DataBits = Convert.ToInt32(_configDoc.DataBits);
                _serialPort.StopBits = _configDoc.StopBits;
                //_localIPAddress = _configDoc.LocalIPAddress;
                _TCPPort = Convert.ToInt32(_configDoc.TCPPort);
                _ResponseWait = Convert.ToInt32(_configDoc.ResponseWait);
                _SerialTimeout = Convert.ToInt32(_configDoc.SerialTimeout);

                _serialPort.Handshake = Handshake.None;
                //SORABH - Do we need this wired event?
                //_serialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPort_DataReceived);
                _serialPort.ReadTimeout = _SerialTimeout;
                _serialPort.WriteTimeout = _SerialTimeout;
                _serialPort.DtrEnable = true;
                _serialPort.RtsEnable = true;
                _serialPort.Open();

                //if (keepPortOpen == false)
                //{
                //    _serialPort.Close();
                //}

                //_backgroundWorker = new BackgroundWorker();
                //_backgroundWorker.WorkerReportsProgress = true;
                //_backgroundWorker.WorkerSupportsCancellation = true;
                //_backgroundWorker.DoWork += BackgroundWorker_DoWork;
                //_backgroundWorker.RunWorkerAsync("Background Worker");   

                _FlagServiceStarted = true;
            }
            else
            {
                Utility.WriteLog("Serial Port Information not Initialized in Utility -> ");
                return false;
            }                

            return true;

        }
        catch (Exception ex)
        {
            Utility.WriteLog("Unable to open the given Serial Port: CreateSerialPort():-> " + ex.Message);
            return false;
        }
    }

}

}

任何帮助将不胜感激。感谢

2 个答案:

答案 0 :(得分:0)

但是,您希望看到您的例外更简洁地回答:

while((i = networkStream.Read(bytes, 0, bytes.Length))!=0)

这不在你的内部try / catch中,因此从套接字读取的任何错误都将终止你的线程/进程。查看不在try / catch中的代码作为可能的问题。

答案 1 :(得分:0)

解决方法是将数据写回catch块中的网络流。现在是第二次循环,如下所示

// Loop to receive all the data sent by the client. 
                    while ((i = networkStream.Read(bytes, 0, bytes.Length)) != 0)
                    {

                        //System.Diagnostics.Debugger.Launch();

                        // Translate data bytes to a ASCII string.
                        data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
                        Utility.WriteLog("Received: " + data);

                        string CartCommand = data;

                        #region PROCESSING AT COMMAND AT FIRMWARE

                        try
                        {
                            string SerialResponse = string.Empty;
                            CreateSerialPort();
                            if (_serialPort.IsOpen == false)
                            {
                                _serialPort.Open();
                            }

                            _serialPort.Write(CartCommand); /* Execute Network Supplied Command to Serial Port */
                            Thread.Sleep(_ResponseWait);

                            byte[] SPResponsebyte = new byte[_serialPort.ReadBufferSize];
                            int intSPtBytes = _serialPort.Read(SPResponsebyte, 0, SPResponsebyte.Length); /* Read the Serial Port Response after Command Execution */
                            SerialResponse = System.Text.Encoding.ASCII.GetString(SPResponsebyte, 0, intSPtBytes);

                            SPResponsebyte = System.Text.Encoding.ASCII.GetBytes(SerialResponse);
                            networkStream.Write(SPResponsebyte, 0, SPResponsebyte.Length);

                            Utility.WriteLog(SerialResponse);
                        }
                        catch (Exception ex)
                        {
                            Utility.WriteLog("Error: " + ex.Message);

                            byte[] SPResponsebyte = new byte[_serialPort.ReadBufferSize];
                            SPResponsebyte = System.Text.Encoding.ASCII.GetBytes("COMERROR"); // explicitly initializing with blank response
                            networkStream.Write(SPResponsebyte, 0, SPResponsebyte.Length); // force output to network stream

                            Utility.WriteLog("Blank response sent back to network stream");

                            // This is the problem area, the while loop don't accept next commands after this.
                        }

                        #endregion

                    }

非常感谢基思提出的宝贵建议。