在套接字客户端中增加内存使用量
问题描述:
我正在尝试开发一个在C#中作为异步套接字客户端运行的控制台应用程序。你可以看到下面的代码:在套接字客户端中增加内存使用量
public class StateObject
{
// Client socket.
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
class Program
{
private static readonly string hostIp = ConfigurationManager.AppSettings["HostIp"];
private static readonly int port = Int32.Parse(ConfigurationManager.AppSettings["HostPort"]);
private static Socket client;
private static ManualResetEvent connectDone = new ManualResetEvent(false);
private static ManualResetEvent sendDone = new ManualResetEvent(false);
private static ManualResetEvent receiveDone = new ManualResetEvent(false);
private static Thread receiveThread;
static int Main(string[] args)
{
EventLog appLog = new EventLog();
appLog.Source = "xApp";
try
{
IPHostEntry ipHostInfo = Dns.GetHostEntry(hostIp);
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
// Create a TCP/IP socket.
client = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
// Connect to the remote endpoint.
client.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback), client);
connectDone.WaitOne();
// Send test data to the remote device.
Send(client, "Login Message");
sendDone.WaitOne();
receiveThread = new Thread((ThreadStart)delegate
{
while (true)
{
Receive(client);
receiveDone.WaitOne();
Thread.Sleep(1);
}
});
receiveThread.Start();
}
catch (Exception ex)
{
appLog.WriteEntry(
"An exception occured: " +
" ex: " + ex.ToString() +
" stack trace: " + ex.StackTrace,
System.Diagnostics.EventLogEntryType.Error);
}
return 0;
}
private static void Receive(Socket client)
{
try
{
// Create the state object.
StateObject state = new StateObject();
state.workSocket = client;
// Begin receiving the data from the remote device.
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
// Retrieve the state object and the client socket
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
// Read data from the remote device.
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
Console.WriteLine("Response received : {0}", state.sb.ToString());
string[] args = state.sb.ToString().Split(';');
switch (args[1])
{
case "CREATEBOOK":
ProcessInput(args);
break;
case "CONFIRMBOOK":
if (args[2] == "true")
{
ConfirmProcess();
}
break;
default:
break;
}
receiveDone.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void Send(Socket client, String data)
{
byte[] byteData = Encoding.Unicode.GetBytes(data);
client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), client);
}
private static void SendCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
int bytesSent = client.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", bytesSent);
// Signal that all bytes have been sent.
sendDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private static void ConnectCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object.
Socket client = (Socket)ar.AsyncState;
// Complete the connection.
client.EndConnect(ar);
Console.WriteLine("Socket connected to {0}",
client.RemoteEndPoint.ToString());
// Signal that the connection has been made.
connectDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
当我调试我看到代码做的工作如预期,但由进程使用的内存大小是增加的每一刻。我认为内存泄漏的原因是以下代码片:
receiveThread = new Thread((ThreadStart)delegate
{
while (true)
{
Receive(client);
receiveDone.WaitOne();
Thread.Sleep(1);
}
});
receiveThread.Start();
但是我对我必须做的改变没有任何想法。你有小费吗?
由于提前,
答
我认为这个问题是在你Receive
方法,您在while
循环中调用。基本上,您每次循环时都会创建一个新的StateObject
。
// Create the state object.
StateObject state = new StateObject();
尝试并将状态对象存储为类变量并重用它。如果您需要重新初始化,可能需要添加Reset
方法。 This article展示了一种构建非常高效的异步套接字的方法,您可能会发现它很有用。
为什么在总是等待结果时使用异步IO?这给你两个世界中最糟糕的。 – usr
您发布的代码中没有任何内容会解释_continuous_内存使用量的增加。由于GC的工作方式,在稳定之前可以看到内存使用量增加到某个点,这是完全正常和可接受的。但是请注意usr的评论:如果你要使用'BeginReceive()',你不应该在循环中等待I/O完成。相反,只需调用'BeginReceive()',然后从完成回调中再次调用它以开始下一次接收。如果您认为自己有真正的内存泄漏问题,请发布[一个很好的完整代码示例](https://*.com/help/mcve)。 –