【发布时间】:2014-12-31 11:58:05
【问题描述】:
我正在尝试开发一个控制台应用程序,在 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();
但我不知道我必须做的改变。你有什么建议吗?
提前致谢,
【问题讨论】:
-
为什么总是在等待结果时使用异步 IO?这给了你两全其美。
-
您发布的代码中没有任何内容可以解释内存使用量持续增加。由于 GC 的工作方式,您可能会看到内存使用量在稳定之前增加到某个点,这是完全正常且可以接受的。但请注意 usr 的评论:如果您要使用
BeginReceive(),则不应在循环中等待 I/O 完成。相反,只需调用BeginReceive(),然后从您的完成回调中再次调用它以开始下一次接收。如果您认为自己有真正的内存泄漏问题,请发布a good, complete code example。
标签: c# sockets asynchronous console-application asyncsocket