Problem with .NET sockets

T

Timothy Shih

Hi,

I am experiencing an intermittent problem while using .NET sockets. I have
an application which opens several sockets -- and in the event that any of
them fail, lose connection, or otherwise stop working, attempts to
re-establish the connection. After a few days I receive an error like the
following:
at System.Net.Sockets.Socket.BeginConnect(EndPoint remoteEP, AsyncCallback
callback, Object state)
at Sensicast.Protocol_Service.ServerClient.ConnectSocket()
An operation on a socket could not be performed because the system lacked
sufficient buffer space or because a queue was fullI was not sure of what
the problem was, so I searched for the error string online and I found the
following on the Microsoft support
site:http://support.microsoft.com/?id=826757The error string is the same as
the one I am getting, but I am not sure if this is the issue. If it is the
issue however, is there a way I can obtain the hotfix without having to go
through the support site? (which charges per call)Thanks,Timothy Shih
 
W

William Stacey [MVP]

I would guess it has something to do with your use of BeginConnect and maybe
some run away connects using up sock stack memory or something. Even when
using async, I don't see much value in using BeginConnect. Just use the
blocking connect in a seperate thread. Then on connect, create a new thread
for the client or use async begins as your needs dictate. This is a good
test anyway to see if the error is coming from your usage of beginConnect or
other. hth
 
B

Bryan 'CapnBry' Mayland

I'd say that when it fails, check the Task Manager and see if you've got an absurd number of handles
in use by your application. It may be the same issue I decribed in detail a few days ago (and a
year ago for that matter), where a socket that fails a connection attempt will leak a wait handle
each time it fails.

Also, make sure that every time the connect fails, loses connection, or otherwise stops working,
that you call Close() before you discard the reference to the socket object.

Here is my sample code that leaks the handle every time, reproducable in all public versions of the
..NET CLR:
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
/// <summary>
/// Test application for triggering a handle leak when a "connection refused"
/// exception is raised in an async socket connection attempt.
/// </summary>
class Class1
{
private static bool _terminated = false;

[DllImport("KERNEL32.DLL", EntryPoint="CloseHandle", SetLastError=true,
ExactSpelling=true, CallingConvention=CallingConvention.StdCall)]
public static extern bool CloseHandle(int hObject);
[DllImport("KERNEL32.DLL", CallingConvention=CallingConvention.StdCall)]
public static extern int GetLastError();

[STAThread]
static void Main(string[] args)
{
Thread _runner = new Thread(new ThreadStart(runner_execute));
_runner.Start();
System.Console.WriteLine("Press ENTER to exit...");
System.Console.ReadLine();
_terminated = true;
_runner.Join();
}

private static void runner_execute()
{
while (!_terminated)
{
StartConnect();
System.Threading.Thread.Sleep(2000);
}
}

// What port to try to connect to. Ideally this should be set to a port
// on the local machine which is not listening or firewalled. That guarantees
// we'll get a good ole 10061 WSAECONNREFUSED error when the connect fails.
// With each connection attempt, 3 handles are allocated. 2 are released
// when the socket is Close()d, the third is only released when garbage
// collection is forced. The number of threads stays constant.
//private static string _host = "127.0.0.1";
private static int _port = 10901;

private static void StartConnect()
{
Socket y = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

//IPHostEntry he = Dns.Resolve(_host);
//if (he.AddressList.Length == 0)
// throw new Exception("Could not resolve host " + _host);
//IPEndPoint hostEndPoint = new IPEndPoint(he.AddressList[0], _port);

IPEndPoint hostEndPoint = new IPEndPoint(new IPAddress(0x0100007f), _port); // 127.0.0.1
y.BeginConnect(hostEndPoint, new AsyncCallback(AsyncConnectComplete), y);
}

private static void AsyncConnectComplete(IAsyncResult ar)
{
Socket s = (Socket)ar.AsyncState;
try
{
// throws connection refused
s.EndConnect(ar);
// unreachable in test case, connection will always be refused
//if (!s.Connected)
// throw new Exception("Errar");
}
catch (Exception e)
{
// Must call Close() or will leak all 3 handles.
s.Close();
s = null;
Console.WriteLine(e.Message);
}
}
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top