【发布时间】:2015-04-10 01:56:50
【问题描述】:
我编写了服务器代码,它使用来自多个客户端(超过 500 个)的多线程(异步)连续接收来自服务器的数据。 它从所有客户端读取数据并在多线程方面正常工作并接收客户端发送的所有消息。
有什么问题?
问题是当我在 1 到 2 小时后继续从客户端读取数据时,我的服务器变慢了。我的意思是,它不断增加 CPU 使用率(可能是因为释放内存……因为这里我们把所有东西都留在垃圾收集器上)。当我在 CPU 中看到内存在一段时间后从 14% 突然上升到 80-100% 时。但它仍然从客户端接收数据(但有些数据泄漏)但它仍然接收。而且我无法确定问题的原因。
有人可以告诉我这可能是什么基本原因吗?
代码的重要部分是:
public void StartServer()
{
try
{
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, port);
server.Bind(ipep);
server.Listen(4);
AppendIncomingData(txtMsg, "Server Started..");
btnStart.Enabled = false;
lblStartDate.Text = DateTime.Now.ToString();
server.BeginAccept(new AsyncCallback(AcceptConn), server);
}
catch (Exception ex)
{
AppendIncomingData(txtError, ex.Message);
}
}
void AcceptConn(IAsyncResult ia)
{
Socket client;
try
{
Socket oldserver = (Socket) ia.AsyncState;
client = oldserver.EndAccept(ia);
StateObject state = new StateObject();
state.workSocket = client;
client.ReceiveTimeout = 1000;
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveData), state);
server.BeginAccept(new AsyncCallback(AcceptConn), server);
}
catch (Exception ex)
{
AppendIncomingData(txtError, "AcceptConn Exception : " + ex.Message);
}
}
/// <summary>
/// StateObject Class to read data from Client
/// </summary>
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 512;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
public Int64 DeviceId = 0;
}
void ReceiveData(IAsyncResult ia)
{
StateObject state = (StateObject)ia.AsyncState;
Socket client = state.workSocket;
string sql = "";
string stringData = "";
try
{
recv = client.EndReceive(ia);
if (recv == 0)
{
client.Close();
server.BeginAccept(new AsyncCallback(AcceptConn), server);
return;
}
Array.Resize(ref state.buffer, StateObject.BufferSize);
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveData), state);
} //End Try
catch (Exception ex)
{
AppendIncomingData(txtError, "ReceiveData Error : " + stringData + ": " + ex.Message);
client.Close();
server.BeginAccept(new AsyncCallback(AcceptConn), server);
}
}
public void AppendIncomingData(object dataControl, string str)
{
if (btnMsg.Text.ToUpper().Contains("START") == true)
return;
TextBox lst = (TextBox)dataControl;
if (lst.InvokeRequired)
{
AppendIncomingData_Delegate method = new AppendIncomingData_Delegate(AppendIncomingData);
lst.Invoke(method, new object[] { lst, str });
}
else
{
msglines += 1;
if (msglines > 500)
{
msglines = 0;
//lst.Clear();
txtError.Clear();
txtMsg.Clear();
}
lst.AppendText(Environment.NewLine + DateTime.Now.ToString() + " " + str);
}
}
可能是什么问题?
【问题讨论】:
-
我建议您看看互联网上提供的各种免费和商业诊断工具,这可以让您缩小罪魁祸首。
-
这可能不是 问题,但您几乎完全忽略了来自
EndReceive的返回值。这告诉您实际收到了多少字节,这可能与与您请求读取的字节数相同。 TCPs 抽象是一个任意字节流,所以不能保证Send在一端调用和Receive在另一端调用会1-1 匹配。 -
内存泄漏最终会导致内存耗尽而不是减速。由于包含可访问数据的页面在物理内存中被调用,而其他页面被调出到交换文件,因此磁盘活动高将表明出现抖动。抖动是由于缺乏内存来处理应用程序的需求,但不一定是内存泄漏。在这两种情况下,您都没有理由遇到高 CPU 利用率。我认为您应该在其他地方寻找解释。使用分析工具。
标签: c# multithreading asynchronous server asyncsocket