这是我的一个非常简单的TCP服务器的代码(基本上是示例异步服务器套接字示例 - http://goo.gl/Ix5C - 略有修改):
public static void InitiateListener()
{
try
{
allDone = new ManualResetEvent(false);
configFile = new XmlConfig();
StartListening();
}
catch (Exception exc)
{
LogsWriter f = new LogsWriter(configFile.ErrorLogsPath);
f.WriteToFile(exc.Message);
f.CloseFile();
}
}
private static void StartListening()
{
try
{
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, configFile.Port);
Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(localEndPoint);
listener.Listen(100);
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
}
catch (Exception exc)
{
throw exc;
}
}
public static void AcceptCallback(IAsyncResult ar)
{
allDone.Set(); // Signal the main thread to continue.
// Get the socket that handles the client request.
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// Create the state object.
StateObject state = new StateObject();
state.workSocket = handler;
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
}
public static void ReadCallback(IAsyncResult ar)
{
string hexData = string.Empty;
// Retrieve the state object and the handler socket from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
try
{
// Read data from the client socket.
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
hexData = BitConverter.ToString(state.buffer);
if (hexData.Contains("FA-F8")) //heartbeat - echo the data back to the client.
{
byte[] byteData = state.buffer.Take(bytesRead).ToArray();
handler.Send(byteData);
}
else if (hexData.Contains("0D-0A")) //message
{
state.AsciiData = Encoding.ASCII.GetString(state.buffer, 0, bytesRead);
state.ParseMessage(configFile);
}
}
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
}
catch (Exception)
{
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
}
这一切都在Windows服务中。大约2天半的运行完全可以接受后,CPU最大可达100%。这已经发生了3次 - Windows服务总是运行正常并且按照预期运行,几乎没有CPU资源,但是第3天的某个时间达到100%并保持在那里,直到服务被重新启动。
我得到非常简单的CSV数据包,我快速解析并通过此方法中的webservice将其发送到数据库: state.ParseMessage(CONFIGFILE); 即使CPU为100%,数据库也会非常可靠地填满。但我知道这可能是我需要调查的地方吗?
代码的哪些其他区域似乎可能导致问题?我是异步编程的新手,所以我不知道是否需要手动关闭线程。此外,这可能是另一个问题:
handler.BeginReceive(state.buffer,0,StateObject.BufferSize,0,new AsyncCallback(ReadCallback),state);
在ReadCallback本身内调用该行。我这样做是为了维持与客户端的连接并继续接收数据,但也许我应该接近套接字并强制建立新连接?
你能提出一些建议吗?感谢
答案 0 :(得分:0)
在startlistening方法中我们需要调用
而不是循环while(true)
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
一旦完成接受新客户端,就从AcceptCallback方法。
答案 1 :(得分:0)
您需要通过bytesRead == 0
检测断开连接。现在你没有,而是发出另一个阅读。
看起来您已经复制了MSDN示例代码。我可以说,因为异步IO和事件的无可比拟的组合。使用同步IO时,所有这些代码都变得更简单。