我有一个监听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;
}
}
}
}
任何帮助将不胜感激。感谢
答案 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
}
非常感谢基思提出的宝贵建议。