Groups | Blog | Home
all groups > dotnet performance > december 2004 >

dotnet performance : Asynchronous socket performance problem



Onder Ozcan
12/22/2004 1:01:04 AM
Dear All,

I developed Asynchronous socket programme with C#. It listens the network at
specific ports and handle IP message requests coming from that port and the
hardware that is used to deploy this application is quite strong.It has 4 IBM
processor and 2 GB memory. At the begining i checked the task manager and
the memory usage was 7.100 K . So far, everything is OK. But after 2 hours ,
i get 7600 requests , i checked the task manager again and i was shocked !
The memory usage was about to 38.000 K ! And the response time had increased
so much (around 20 sec).
I have got serious performance problem and I haven't found source of
this problem. I close the connections and database objects and sockets when
they are done carefully. Is it about memory retention ? Are CLR and garbage
collection suspicious ? What do i have to do ?


Here is the code that i implemented based on microsoft advices.

Best regards,
Onder OZCAN
Ankara, TURKEY






// Begin to listen
protected void StartListening()
{
try
{
// Bind the socket to the local endpoint and listen for incoming
connections.
m_listenerSocket.Bind(m_localEndPoint);
m_listenerSocket.Listen(m_pendingConnection);

statusBar1.Text="... Waiting for a connection at port: " +
m_port.ToString();

while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();

// Start an asynchronous socket to listen for connections.
m_listenerSocket.BeginAccept(new
AsyncCallback(this.BeginAcceptCallback),m_listenerSocket);

// Blocks current thread until the current WaitHandle receives a signal.
// Moreover, this statement ensures to avoid infinite loop
allDone.WaitOne();
}
}
catch (Exception e)
{
oLog.logError("Error in StartListening(): " + e.Message,
CCnfgMain.APPNAME, EventLogEntryType.Error);
m_listenerSocket.Shutdown(SocketShutdown.Both);
m_listenerSocket.Close();
MessageBox.Show("Socket Başlatma Hatası: " + e.Message + "\n ATM
Listener Yeniden Başlatılmalıdır !..." , " - StartListening - ");
}
}


// Accept incoming socket connection requests asynchronously
protected void BeginAcceptCallback(IAsyncResult p_IAsyncResult)
{
Socket v_listenerSocket=null ;
Socket v_handlerSocket=null ;
StateObject state=null ;

try
{
// Signal the main thread to continue.
allDone.Set();

// Get the socket that handles the client request.
v_listenerSocket = (Socket) p_IAsyncResult.AsyncState;
v_handlerSocket = v_listenerSocket.EndAccept(p_IAsyncResult);

// Create the state object.
state = new StateObject();
state.workSocket = v_handlerSocket;

if (v_handlerSocket.Connected)
{
//Begin to receive client's data
v_handlerSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(this.BeginReceiveCallback), state);
}
else
{
// remote device is not connected
v_handlerSocket.Shutdown(SocketShutdown.Both);
v_handlerSocket.Close();
}
}
catch (Exception e)
{
oLog.logError("Error in BeginAcceptCallback(): " + e.Message
,CCnfgMain.APPNAME, EventLogEntryType.Error);
// v_handlerSocket.Shutdown(SocketShutdown.Both);
v_handlerSocket.Close();
MessageBox.Show("BeginAcceptCallback Error: " + e.Message , " -
BeginAcceptCallback - " );
}
}


// Read incoming socket connection requests asynchronously
protected void BeginReceiveCallback(IAsyncResult p_IAsyncResult)
{
string content ="";
string strResponse ="";
int bytesRead;
string v_msgIn;
string v_msgID;

StateObject state=null ;
Socket v_handlerSocket=null ;

try
{
// Retrieve the state object and the handler socket
// from the asynchronous state object.
state = (StateObject) p_IAsyncResult.AsyncState;
v_handlerSocket = state.workSocket;

// Read data from the client socket.
// return value : The number of bytes received
bytesRead = v_handlerSocket.EndReceive(p_IAsyncResult);

if (bytesRead > 0)
{
#region "Pozitif Data Stream (bytesRead >0)"

// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer,0,bytesRead));

// Check for end-of-file tag. If it is not there, read more data.
content = state.sb.ToString();

// pure incoming mesaage
v_msgIn = state.sb.ToString().Trim(new
char[]{'\x02','\x00','\x03'});
v_msgIn = v_msgIn.TrimStart(new char[]{'.'});
v_msgIn = v_msgIn.TrimEnd(new char[]{'.'});
txtReceived.Text += v_msgIn + "\n";

// get the msgid
v_msgID =
v_msgIn.Substring(CCnfgMain.MSG_ID_OFF,CCnfgMain.MSG_ID_OFFLNG).ToUpper();

//if client data contains "<EOF>" string , it is clear that the data is
totally received
if ( true )
{
// just echo incoming message
strResponse = v_msgIn ;

if (v_handlerSocket.Connected)
{
txtSent.Text +=strResponse + "\n";

if (v_msgID=="001" || v_msgID=="002")
{
strResponse ='.'.ToString() + strResponse + '.'.ToString() +
'.'.ToString();
}
else
{
strResponse ='\x02'.ToString() + strResponse + '\x03'.ToString();
}

// Echo the data back to the client.
Send(v_handlerSocket,strResponse);
}
else
{
// not connected
v_handlerSocket.Shutdown(SocketShutdown.Both);
v_handlerSocket.Close();
}
}
else
{
if (v_handlerSocket.Connected)
{
// Not all data received. Get more.
v_handlerSocket.BeginReceive(state.buffer, 0, StateObject.BufferSize,
0,
new AsyncCallback(this.BeginReceiveCallback), state);
}
else
{
// not connected
v_handlerSocket.Shutdown(SocketShutdown.Both);
v_handlerSocket.Close();
}
}
#endregion
}
}
catch (Exception e)
{
oLog.logError("Error in BeginReceiveCallback(): " +
e.Message,CCnfgMain.APPNAME , EventLogEntryType.Error);
// v_handlerSocket.Shutdown(SocketShutdown.Both);
v_handlerSocket.Close();
MessageBox.Show("BeginReceiveCallback Error: " + e.Message , " -
BeginReceiveCallback - ");
}
}


// Send the response to the caller
protected void Send(Socket p_handler, String p_data)
{
byte[] byteData ;

try
{
// Convert the string data to byte data using ASCII encoding.
byteData = Encoding.ASCII.GetBytes(p_data);

if (p_handler.Connected)
{
// Begin sending the data to the remote device.
Amal
2/9/2005 8:23:02 AM
Onder,

Why are you closing the socket after handling the request? Could it be that
your client is expecting that once a connection is made that it will be there
for further request? If that is the case then you're creating a lot of
overhead for the client because it is having to re-establish the connection
for each request which is inefficient and will cause considerable delays.

This might also explain the jump in memory usage because you keep creating a
lot of new threads for each incoming request from the same client whereas one
would've done the job.

Please take a look at the thread titled "Problem with Socket Performance" in
this newsgroup.You might find it helpful.

Regards,
Amal



[quoted text, click to view]
AddThis Social Bookmark Button