2

I've written a tcp socket prgram that working with sockets asyncoronously.

This is some part of my code:

public void main()
{
   var e = new SocketAsyncEventArgs();
   e.Completed += new EventHandler<SocketAsyncEventArgs>(e_Completed);
   Task.Factory.StartNew(() =>
   {                        
         allDone.Reset();
         mySocket.AcceptAsync(e);
         allDone.WaitOne();                       
   });
}

public void e_Completed(object sender, SocketAsyncEventArgs e)
{
     var socket = (Socket)sender;
     ThreadPool.QueueUserWorkItem(HandleTcpRequest, e.AcceptSocket);
     e.AcceptSocket = null;
     socket.AcceptAsync(e);
}

public void HandleTcpRequest(object state)
{
    var mySocket = (Socket)state;
    try
    {
       //do some codes and work with mySocket 
    }
    catch (Exception ex)
    {
    }
    finally
    {
        mySocket.Close();
        mySocket.Dispose();
    }
}

I've seen lots of \device\afd in process explorer in my process. I've read and searched a lot about this and found that it is related to the Ancillary Function Driver and the Transport Driver Interface. How can I resolve this handle leak?

==========> edited my code:

Edited to accept only 10 sockets in sync way.

Feel that program is more faster, but when push my finger on Ctrl+F5, find that there are more than 10 \device\afd in process explorer and when continuing too push, see more \device\afd, but lower that above code.

 mySocket.Listen(10);
 while (true)
 {                                                
      using (Socket so = mySocket.Accept())
      {
            HandleTcpRequest(so);
      }   
 }
Reza Akraminejad
  • 1,412
  • 3
  • 24
  • 38
  • You posted 3 methods that are completely unrelated to each other. Please post a [mcve] – Camilo Terevinto Mar 14 '18 at 11:59
  • You code never teminates. Noting is setting the allDone waithandle. So you think the program is closing when it is not really closing. See following posting for a suggestion of fixing issue : https://social.msdn.microsoft.com/Forums/sqlserver/en-US/3295e38d-2267-425a-a7f8-9e6035331e53/how-to-capture-closing-of-c-console-apps?forum=csharpgeneral – jdweng Mar 14 '18 at 12:06
  • @CamiloTerevinto I've edited my code – Reza Akraminejad Mar 14 '18 at 12:11
  • @jdweng I've edited my code – Reza Akraminejad Mar 14 '18 at 12:11
  • 1
    No offense intended, but your mix of thread pool code, synchronous waiting on handles and tasks suggests to me that you're using `SocketAsyncEventArgs` when you have not yet mastered the intricacies of network code to the point where you can profitably use it. Consider using `TcpClient` in an asynchronous manner, or, if you do need to go beyond that, the async versions of the `Socket` methods. `SocketAsyncEventArgs` is advanced stuff that should really only go in servers that need to process a ton of load and have exhausted other obvious avenues of optimization, as it's not the easiest API. – Jeroen Mostert Mar 14 '18 at 12:17
  • I don't know why you need the Task.Factory. The code runs asynchronously already and you have the WaitHandle to block so the program does't terminate. The Task.Factory is crating the memory leak because the Task.Factory lets the process continue after the application closes. – jdweng Mar 14 '18 at 12:28
  • For `TcpClient` in my remark above, read `TcpListener`, of course. – Jeroen Mostert Mar 14 '18 at 12:29
  • @JeroenMostert I've edited my code, please look at description in edited in lower part. Thanks – Reza Akraminejad Mar 14 '18 at 12:35
  • @jdweng I've used Task.Factory because multiple IPs may bind in same program. – Reza Akraminejad Mar 14 '18 at 12:36
  • `using (Socket)`. Dispose your disposable resources. Asynchronous code makes this trickier (on occasion), but doesn't remove the basic requirement. Beyond that, there is simply no need to fret about the number of handles unless you can demonstrate that they continuously increase over the course of running your program, despite you disposing of everything properly. In particular, there could be a bunch of preallocated or cached objects that won't disappear until your process ends. – Jeroen Mostert Mar 14 '18 at 12:40
  • @JeroenMostert I've forgotten to write that in finally block I use mySocket.Dispose(); Isn't it enough? – Reza Akraminejad Mar 14 '18 at 12:43
  • I was only talking about your last sample. – Jeroen Mostert Mar 14 '18 at 12:44
  • Each IP will have it own instance of the process so putting it in a Task.Factory will do nothing except create a memory leak. – jdweng Mar 14 '18 at 12:46
  • @JeroenMostert I've changed last part, but stil when pushing ctrl+F5, \device\afd handles increase, and when open new tab to send a new request, it waits until first tab (which ctrl+F5 pushed for one minute) loads and answers second tab. – Reza Akraminejad Mar 14 '18 at 12:58
  • @JeroenMostert Any idea about removing same requests from same client that pushing ctrl+F5? Don't want to waste server resources and put other clients in queue. Is there any standard way that many webservers doing that? Or I should add some configuration to socket ? – Reza Akraminejad Mar 15 '18 at 06:18

0 Answers0