Added the following code .
if (iRx < 1) {
m_workerSocketList[socketData.m_clientNumber - 1] =null;
socketData.m_currentSocket.Shutdown(SocketShutdown.Both);
socketData.m_currentSocket.Close();
m_workerSocketList.Remove(socketData);
socketData = null;
socketData.m_currentSocket = null;
socketData.dataBuffer = null;
string Mesg = socketData.m_currentSocket.RemoteEndPoint + " Disconnected" + "\n";
//m_mainSocket.Disconnect(false);
GC.Collect();
GC.WaitForPendingFinalizers();
}
Is this correct ? Where do you I call workerSocket.Dispose? Still memory is increasing.
This is a TCP socket server which has to receive data from TCP clients (may be async or sync) and send the data to MSMQ. This exe must run forever in production. I notice that the memory of the exe increases steadily from 11 K to 500 K in a few hours. Can anybody please help me review the code for any memory leak or any other problem.
public class SocketServer : System.Windows.Forms.Form
{
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.RichTextBox richTextBoxReceivedMsg;
private System.Windows.Forms.TextBox textBoxPort;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.TextBox textBoxMsg;
private System.Windows.Forms.Button buttonStopListen;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.RichTextBox richTextBoxSendMsg;
private System.Windows.Forms.TextBox textBoxIP;
private System.Windows.Forms.Button buttonStartListen;
private System.Windows.Forms.Button buttonSendMsg;
private System.Windows.Forms.Button buttonClose;
public delegate void UpdateRichEditCallback(string text);
public delegate void UpdateClientListCallback();
public AsyncCallback pfnWorkerCallBack;
private Socket m_mainSocket;
// An ArrayList is used to keep track of worker sockets that are designed
// to communicate with each connected client. Make it a synchronized ArrayList
// For thread safety
private System.Collections.ArrayList m_workerSocketList =
ArrayList.Synchronized(new System.Collections.ArrayList());
// The following variable will keep track of the cumulative
// total number of clients connected at any time. Since multiple threads
// can access this variable, modifying this variable should be done
// in a thread safe manner
private int m_clientCount = 0;
private System.Windows.Forms.ListBox listBoxClientList;
private Button btnClear;
private System.Windows.Forms.Label label6;
public SocketServer()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
// Display the local IP address on the GUI
textBoxIP.Text = GetIP();
}
[STAThread]
public static void Main(string[] args)
{
Application.Run(new SocketServer());
}
#region Windows Forms Designer generated code
/// <summary>
/// This method is required for Windows Forms designer support.
/// Do not change the method contents inside the source code editor. The Forms designer might
/// not be able to load this method if it was changed manually.
/// </summary>
private void InitializeComponent()
{
this.buttonClose = new System.Windows.Forms.Button();
this.buttonSendMsg = new System.Windows.Forms.Button();
this.buttonStartListen = new System.Windows.Forms.Button();
this.textBoxIP = new System.Windows.Forms.TextBox();
this.richTextBoxSendMsg = new System.Windows.Forms.RichTextBox();
this.label1 = new System.Windows.Forms.Label();
this.buttonStopListen = new System.Windows.Forms.Button();
this.textBoxMsg = new System.Windows.Forms.TextBox();
this.label4 = new System.Windows.Forms.Label();
this.label5 = new System.Windows.Forms.Label();
this.textBoxPort = new System.Windows.Forms.TextBox();
this.richTextBoxReceivedMsg = new System.Windows.Forms.RichTextBox();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.listBoxClientList = new System.Windows.Forms.ListBox();
this.label6 = new System.Windows.Forms.Label();
this.btnClear = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// buttonClose
//
this.buttonClose.Location = new System.Drawing.Point(701, 465);
this.buttonClose.Name = "buttonClose";
this.buttonClose.Size = new System.Drawing.Size(88, 24);
this.buttonClose.TabIndex = 11;
this.buttonClose.Text = "Close";
this.buttonClose.Visible = false;
this.buttonClose.Click += new System.EventHandler(this.ButtonCloseClick);
//
// buttonSendMsg
//
this.buttonSendMsg.Location = new System.Drawing.Point(701, 465);
this.buttonSendMsg.Name = "buttonSendMsg";
this.buttonSendMsg.Size = new System.Drawing.Size(192, 24);
this.buttonSendMsg.TabIndex = 7;
this.buttonSendMsg.Text = "Send Message";
this.buttonSendMsg.Visible = false;
this.buttonSendMsg.Click += new System.EventHandler(this.ButtonSendMsgClick);
//
// buttonStartListen
//
this.buttonStartListen.BackColor = System.Drawing.SystemColors.ButtonShadow;
this.buttonStartListen.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.buttonStartListen.ForeColor = System.Drawing.SystemColors.ActiveCaptionText;
this.buttonStartListen.Location = new System.Drawing.Point(227, 16);
this.buttonStartListen.Name = "buttonStartListen";
this.buttonStartListen.Size = new System.Drawing.Size(88, 40);
this.buttonStartListen.TabIndex = 4;
this.buttonStartListen.Text = "Start Listening";
this.buttonStartListen.UseVisualStyleBackColor = false;
this.buttonStartListen.Click += new System.EventHandler(this.ButtonStartListenClick);
//
// textBoxIP
//
this.textBoxIP.Location = new System.Drawing.Point(88, 16);
this.textBoxIP.Name = "textBoxIP";
this.textBoxIP.ReadOnly = true;
this.textBoxIP.Size = new System.Drawing.Size(120, 20);
this.textBoxIP.TabIndex = 12;
//
// richTextBoxSendMsg
//
this.richTextBoxSendMsg.Location = new System.Drawing.Point(701, 465);
this.richTextBoxSendMsg.Name = "richTextBoxSendMsg";
this.richTextBoxSendMsg.Size = new System.Drawing.Size(192, 57);
this.richTextBoxSendMsg.TabIndex = 6;
this.richTextBoxSendMsg.Text = "";
this.richTextBoxSendMsg.Visible = false;
this.richTextBoxSendMsg.TextChanged += new System.EventHandler(this.richTextBoxSendMsg_TextChanged);
//
// label1
//
this.label1.Location = new System.Drawing.Point(16, 40);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(48, 16);
this.label1.TabIndex = 1;
this.label1.Text = "Port";
//
// buttonStopListen
//
this.buttonStopListen.BackColor = System.Drawing.SystemColors.ControlDark;
this.buttonStopListen.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.buttonStopListen.ForeColor = System.Drawing.Color.White;
this.buttonStopListen.Location = new System.Drawing.Point(321, 16);
this.buttonStopListen.Name = "buttonStopListen";
this.buttonStopListen.Size = new System.Drawing.Size(88, 40);
this.buttonStopListen.TabIndex = 5;
this.buttonStopListen.Text = "Stop Listening";
this.buttonStopListen.UseVisualStyleBackColor = false;
this.buttonStopListen.Click += new System.EventHandler(this.ButtonStopListenClick);
//
// textBoxMsg
//
this.textBoxMsg.BackColor = System.Drawing.SystemColors.Control;
this.textBoxMsg.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.textBoxMsg.ForeColor = System.Drawing.SystemColors.HotTrack;
this.textBoxMsg.Location = new System.Drawing.Point(105, 488);
this.textBoxMsg.Name = "textBoxMsg";
this.textBoxMsg.ReadOnly = true;
this.textBoxMsg.Size = new System.Drawing.Size(191, 13);
this.textBoxMsg.TabIndex = 14;
this.textBoxMsg.Text = "None";
this.textBoxMsg.TextChanged += new System.EventHandler(this.textBoxMsg_TextChanged);
//
// label4
//
this.label4.Location = new System.Drawing.Point(601, 465);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(192, 16);
this.label4.TabIndex = 8;
this.label4.Text = "Broadcast Message To Clients";
this.label4.Visible = false;
this.label4.Click += new System.EventHandler(this.label4_Click);
//
// label5
//
this.label5.Location = new System.Drawing.Point(392, 69);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(192, 16);
this.label5.TabIndex = 10;
this.label5.Text = "Data Packets Received From Clients";
//
// textBoxPort
//
this.textBoxPort.Loca;tion = new System.Drawing.Point(88, 40);
this.textBoxPort.Name = "textBoxPort";
this.textBoxPort.Size = new System.Drawing.Size(40, 20);
this.textBoxPort.TabIndex = 0;
this.textBoxPort.Text = "9999";
//
// richTextBoxReceivedMsg
//
this.richTextBoxReceivedMsg.BackColor = System.Drawing.SystemColors.InactiveCaptionText;
this.richTextBoxReceivedMsg.Location = new System.Drawing.Point(217, 88);
this.richTextBoxReceivedMsg.Name = "richTextBoxReceivedMsg";
this.richTextBoxReceivedMsg.ReadOnly = true;
this.richTextBoxReceivedMsg.Size = new System.Drawing.Size(676, 368);
this.richTextBoxReceivedMsg.TabIndex = 9;
this.richTextBoxReceivedMsg.Text = "";
this.richTextBoxReceivedMsg.TextChanged += new System.EventHandler(this.richTextBoxReceivedMsg_TextChanged);
//
// label2
//
this.label2.Location = new System.Drawing.Point(16, 16);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(56, 16);
this.label2.TabIndex = 2;
this.label2.Text = "Server IP";
//
// label3
//
this.label3.Location = new System.Drawing.Point(12, 476);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(87, 31);
this.label3.TabIndex = 13;
this.label3.Text = "Status Message:";
this.label3.Click += new System.EventHandler(this.label3_Click);
//
// listBoxClientList
//
this.listBoxClientList.BackColor = System.Drawing.SystemColors.Control;
this.listBoxClientList.Location = new System.Drawing.Point(12, 88);
this.listBoxClientList.Name = "listBoxClientList";
this.listBoxClientList.ScrollAlwaysVisible = true;
this.listBoxClientList.Size = new System.Drawing.Size(195, 368);
this.listBoxClientList.TabIndex = 15;
this.listBoxClientList.SelectedIndexChanged += new System.EventHandler(this.listBoxClientList_SelectedIndexChanged);
//
// label6
//
this.label6.Location = new System.Drawing.Point(15, 69);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(145, 16);
this.label6.TabIndex = 16;
this.label6.Text = "Connected Clients";
this.label6.Click += new System.EventHandler(this.label6_Click);
//
// btnClear
//
this.btnClear.Location = new System.Drawing.Point(700, 465);
this.btnClear.Name = "btnClear";
this.btnClear.Size = new System.Drawing.Size(83, 28);
this.btnClear.TabIndex = 18;
this.btnClear.Text = "Clear";
this.btnClear.Visible = false;
this.btnClear.Click += new System.EventHandler(this.btnClear_Click_1);
//
// SocketServer
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(925, 555);
this.Controls.Add(this.btnClear);
this.Controls.Add(this.label6);
this.Controls.Add(this.listBoxClientList);
this.Controls.Add(this.textBoxMsg);
this.Controls.Add(this.textBoxIP);
this.Controls.Add(this.textBoxPort);
this.Controls.Add(this.label3);
this.Controls.Add(this.buttonClose);
this.Controls.Add(this.label5);
this.Controls.Add(this.richTextBoxReceivedMsg);
this.Controls.Add(this.label4);
this.Controls.Add(this.buttonSendMsg);
this.Controls.Add(this.richTextBoxSendMsg);
this.Controls.Add(this.buttonStopListen);
this.Controls.Add(this.buttonStartListen);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Name = "SocketServer";
this.Text = "MSMQTool";
this.Load += new System.EventHandler(this.SocketServer_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
void ButtonStartListenClick(object sender, System.EventArgs e)
{
try
{
// Check the port value
if (textBoxPort.Text == "")
{
MessageBox.Show("Please enter a Port Number");
return;
}
string portStr = textBoxPort.Text;
int port = System.Convert.ToInt32(portStr);
// Create the listening socket...
m_mainSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
IPEndPoint ipLocal = new IPEndPoint(IPAddress.Any, port);
// Bind to local IP Address...
m_mainSocket.Bind(ipLocal);
// Start listening...
m_mainSocket.Listen(1000);
// Create the call back for any client connections...
m_mainSocket.BeginAccept(new AsyncCallback(OnClientConnect), null);
UpdateControls(true);
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
}
private void UpdateControls(bool listening)
{
buttonStartListen.Enabled = !listening;
buttonStopListen.Enabled = listening;
}
// This is the call back function, which will be invoked when a client is connected
public void OnClientConnect(IAsyncResult asyn)
{
try
{
// Here we complete/end the BeginAccept() asynchronous call
// by calling EndAccept() - which returns the reference to
// a new Socket object
Socket workerSocket = m_mainSocket.EndAccept(asyn);
// Now increment the client count for this client
// in a thread safe manner
Interlocked.Increment(ref m_clientCount);
// Add the workerSocket reference to our ArrayList
m_workerSocketList.Add(workerSocket);
// Update the list box showing the list of clients (thread safe call)
//UpdateClientListControl();
// Let the worker Socket do the further processing for the
// just connected client
WaitForData(workerSocket, m_clientCount);
// Since the main Socket is now free, it can go back and wait for
// other clients who are attempting to connect
m_mainSocket.BeginAccept(new AsyncCallback(OnClientConnect), null);
}
catch (ObjectDisposedException)
{
System.Diagnostics.Debugger.Log(0, "1", "\n OnClientConnection: Socket has been closed\n");
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
}
public class SocketPacket
{
// Constructor which takes a Socket and a client number
public SocketPacket(System.Net.Sockets.Socket socket, int clientNumber)
{
m_currentSocket = socket;
m_clientNumber = clientNumber;
}
public System.Net.Sockets.Socket m_currentSocket;
public int m_clientNumber;
// Buffer to store the data sent by the client
public byte[] dataBuffer = new byte[1024];
}
// Start waiting for data from the client
public void WaitForData(System.Net.Sockets.Socket soc, int clientNumber)
{
try
{
if (pfnWorkerCallBack == null)
{
// Specify the call back function which is to be
// invoked when there is any write activity by the
// connected client
pfnWorkerCallBack = new AsyncCallback(OnDataReceived);
}
SocketPacket theSocPkt = new SocketPacket(soc, clientNumber);
soc.BeginReceive(theSocPkt.dataBuffer, 0,
theSocPkt.dataBuffer.Length,
SocketFlags.None,
pfnWorkerCallBack,
theSocPkt);
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
}
// This the call back function which will be invoked when the socket
// detects any client writing of data on the stream
public void OnDataReceived(IAsyncResult asyn)
{
SocketPacket socketData = (SocketPacket)asyn.AsyncState;
try
{
// Complete the BeginReceive() asynchronous call by EndReceive() method
// which will return the number of characters written to the stream
// by the client
int iRx = socketData.m_currentSocket.EndReceive(asyn);
char[] chars = new char[iRx + 1];
// Extract the characters as a buffer
System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
int charLen = d.GetChars(socketData.dataBuffer,
0, iRx, chars, 0);
System.String szData = new System.String(chars);
Console.WriteLine(szData);
if (szData != null && szData != " " && szData != "" && szData != "\n\r\n" && szData != "\r\n")
{
Console.WriteLine(szData);
try
{
MSMQ msmq = new MSMQ();
msmq.InitializeQueue();
msmq.AddData(szData);
msmq = null;
}
catch (Exception ex1)
{
// Logger.Log("Send failure: " + ex1.Message);
writer.WriteToLog("Send failure: " + ex1.Message);
}
}
// Continue the waiting for data on the Socket
WaitForData(socketData.m_currentSocket, socketData.m_clientNumber);
}
catch (ObjectDisposedException)
{
System.Diagnostics.Debugger.Log(0, "1", "\nOnDataReceived: Socket has been closed\n");
}
catch (SocketException se)
{
if (se.ErrorCode == 10054) // Error code for Connection reset by peer
{
string msg = "Client " + socketData.m_clientNumber + " Disconnected" + "\n";
AppendToRichEditControl(msg);
// Remove the reference to the worker socket of the closed client
// so that this object will get garbage collected
m_workerSocketList[socketData.m_clientNumber - 1] = null;
//UpdateClientListControl();
}
else
{
MessageBox.Show(se.Message);
}
}
}
// This method could be called by either the main thread or any of the
// worker threads
private void AppendToRichEditControl(string msg)
{
// Check to see if this method is called from a thread
// other than the one created the control
if (InvokeRequired)
{
// We cannot update the GUI on this thread.
// All GUI controls are to be updated by the main (GUI) thread.
// Hence we will use the invoke method on the control which will
// be called when the Main thread is free
// Do UI update on UI thread
object[] pList = { msg };
richTextBoxReceivedMsg.BeginInvoke(new UpdateRichEditCallback(OnUpdateRichEdit), pList);
}
else
{
// This is the main thread which created this control, hence update it
// directly
OnUpdateRichEdit(msg);
}
}
// This UpdateRichEdit will be run back on the UI thread
// (using System.EventHandler signature
// so we don't need to define a new
// delegate type here)
private void OnUpdateRichEdit(string msg)
{
richTextBoxReceivedMsg.AppendText(msg);
}
private void UpdateClientListControl()
{
if (InvokeRequired) // Is this called from a thread other than the one created
// the control
{
// We cannot update the GUI on this thread.
// All GUI controls are to be updated by the main (GUI) thread.
// Hence we will use the invoke method on the control which will
// be called when the Main thread is free
// Do UI update on UI thread
listBoxClientList.BeginInvoke(new UpdateClientListCallback(UpdateClientList), null);
}
else
{
// This is the main thread which created this control, hence update it
// directly
UpdateClientList();
}
}
void ButtonSendMsgClick(object sender, System.EventArgs e)
{
try
{
string msg = richTextBoxSendMsg.Text;
msg = "Server Msg: " + msg + "\n";
byte[] byData = System.Text.Encoding.ASCII.GetBytes(msg);
Socket workerSocket = null;
for (int i = 0; i < m_workerSocketList.Count; i++)
{
workerSocket = (Socket)m_workerSocketList[i];
if (workerSocket != null)
{
if (workerSocket.Connected)
{
workerSocket.Send(byData);
}
}
}
}
catch (SocketException se)
{
MessageBox.Show(se.Message);
}
}
void ButtonStopListenClick(object sender, System.EventArgs e)
{
CloseSockets();
UpdateControls(false);
}
String GetIP()
{
String strHostName = Dns.GetHostName();
// Find host by name
IPHostEntry iphostentry = Dns.GetHostByName(strHostName);
// Grab the first IP addresses
String IPStr = "";
foreach (IPAddress ipaddress in iphostentry.AddressList)
{
IPStr = ipaddress.ToString();
return IPStr;
}
return IPStr;
}
void ButtonCloseClick(object sender, System.EventArgs e)
{
CloseSockets();
Close();
}
void CloseSockets()
{
if (m_mainSocket != null)
{
m_mainSocket.Close();
}
Socket workerSocket = null;
for (int i = 0; i < m_workerSocketList.Count; i++)
{
workerSocket = (Socket)m_workerSocketList[i];
if (workerSocket != null)
{
workerSocket.Close();
workerSocket = null;
}
}
}
// Update the list of clients that is displayed
void UpdateClientList()
{
listBoxClientList.Items.Clear();
for (int i = 0; i < m_workerSocketList.Count; i++)
{
string clientKey = Convert.ToString(i + 1);
Socket workerSocket = (Socket)m_workerSocketList[i];
if (workerSocket != null)
{
if (workerSocket.Connected)
{
listBoxClientList.Items.Add(clientKey);
}
}
}
}
void SendMsgToClient(string msg, int clientNumber)
{
// Convert the reply to byte array
byte[] byData = System.Text.Encoding.ASCII.GetBytes(msg);
Socket workerSocket = (Socket)m_workerSocketList[clientNumber - 1];
workerSocket.Send(byData);
}
private void btnClear_Click(object sender, System.EventArgs e)
{
richTextBoxReceivedMsg.Clear();
}
private void SocketServer_Load(object sender, EventArgs e)
{
}
private void label4_Click(object sender, EventArgs e)
{
}
private void richTextBoxReceivedMsg_TextChanged(object sender, EventArgs e)
{
}
private void label6_Click(object sender, EventArgs e)
{
}
private void label3_Click(object sender, EventArgs e)
{
}
private void btnClear_Click_1(object sender, EventArgs e)
{
}
private void richTextBoxSendMsg_TextChanged(object sender, EventArgs e)
{
}
private void textBoxMsg_TextChanged(object sender, EventArgs e)
{
}
private void listBoxClientList_SelectedIndexChanged(object sender, EventArgs e)
{
}
}
m_workerSocketList.Removeis never used, so the list grows forever. AndworkerSocket.Disposeis never invoked. – HABO Sep 30 '12 at 14:11