What is the best way to stop a Socket.BeginAccept call?

D

darthghandi

I've created a class to listen to all interfaces and do a
BeginAccept(). Once it gets a connection, it passes the connected
socket off and stores it in a List. Next, it continues to listen for
more incoming connections and does the BeginAccpet() again. It does
an infinite loop this way. My question is: What is the best way to
stop this? I thought about putting a boolean in there, but then what
if it's still waiting for an incoming connection? Can I just close
the socket?
Here is my code for reference:
public class Listener
{
private Socket m_listener;
private ConnectionCallback m_callBack;

public Listener(ConnectionCallback callme)
{
m_callBack = callme;
}

public void AcceptNewConnections()
{
this.AcceptNewConnections(2200);
}

public void AcceptNewConnections(int port)
{
IPEndPoint theEnd = new IPEndPoint(IPAddress.Any, port);
m_listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
m_listener.Bind(theEnd);
Console.WriteLine("Binding to " +
theEnd.Address.ToString() + " on port " + theEnd.Port.ToString());
m_listener.Listen(20); //TODO: make this
configurable
Console.WriteLine("Now listening");
AsyncCallback callme = new AsyncCallback(AddWorkerSocket);
m_listener.BeginAccept(callme, m_listener);
}

private void AddWorkerSocket(IAsyncResult ar)
{
Console.WriteLine("Got a Connection");
Socket hold = (Socket)ar.AsyncState;
Socket work = hold.EndAccept(ar);
if (work.Connected)
{
Console.WriteLine("Accepted a connection from " +
work.RemoteEndPoint.ToString());
m_callBack(work);
}
AsyncCallback callMe = new AsyncCallback(AddWorkerSocket);
hold.BeginAccept(callMe, hold);
}
}
 
C

Crash

I've created a class to listen to all interfaces and do a
BeginAccept(). Once it gets a connection, it passes the connected
socket off and stores it in a List. Next, it continues to listen for
more incoming connections and does the BeginAccpet() again. It does
an infinite loop this way. My question is: What is the best way to
stop this? I thought about putting a boolean in there, but then what
if it's still waiting for an incoming connection? Can I just close
the socket?

It's been a while since I used these APIs but - Yes - I think you can
close the socket. If I recall you will get a "socket closed"
exception so you might want to put a try catch around your
BeginAccept() code...
 
M

Michael Rubinstein

<
It does an infinite loop this way...Does it bother you? Instead of closing the listening socket, you can put a
limit on the number of client connections and issue BeginAccept() only until
that limit is reached. Normally you would close the listening socket only
after you have no clients connected and done with TCP.

Michael
 
D

darthghandi

<
It does an infinite loop this way...

Does it bother you? Instead of closing the listening socket, you can put a
limit on the number of client connections and issue BeginAccept() only until
that limit is reached. Normally you would close the listening socket only
after you have no clients connected and done with TCP.

Michael

I was hoping for an infinite loop, sort of. I would like this to
become a window's service, so I want to listen for incoming
connections until the service is stopped. I was really wondering if
anyone was familiar with the "best way" to stop from this sort of
loop. I have modified the code slightly so that when the service
stops, the list of sockets is looped through. While looping through
the sockets, I call Socket.Close() in order to try to clean up my
mess. It seems to work without throwing any exceptions, but I am just
wondering if this is the right way to do things.
Thanks again for your time and comments. Here is the modified code:
public delegate void ConnectionCallback(Socket sockMe);
public class Controller
{
private Listener m_listen;
private List<Socket> m_wokerList;
//need a connection
//private List<Connection> connectList;

public Controller()
{
m_wokerList = new List<Socket>(20); //TODO: make
this configurable
}

public void Start()
{
m_listen = new Listener(new
ConnectionCallback(this.AddSocketToList));
m_listen.AcceptNewConnections();
}

public void AddSocketToList(Socket sock)
{
Console.WriteLine("Got a socket and adding it to the list
of workers");
m_wokerList.Add(sock);
Console.WriteLine("There are now " +
m_wokerList.Count.ToString() + " sockets in the list.");
if (m_wokerList[m_wokerList.Count - 1].Connected)
{
Console.WriteLine("The last socket is connected to" +
m_wokerList[m_wokerList.Count - 1].RemoteEndPoint.ToString());
}
else
{
Console.WriteLine("The last socket is NOT connected");
}

}

public void Stop()
{
foreach (Socket closeSock in m_wokerList)
{
closeSock.Close();
}
m_listen.StopListening();
}
}
public class Listener
{
private Socket m_listener;
private ConnectionCallback m_callBack;

public Listener(ConnectionCallback callme)
{
m_callBack = callme;
}

public void AcceptNewConnections()
{
this.AcceptNewConnections(2200);
}

public void AcceptNewConnections(int port)
{
IPEndPoint theEnd = new IPEndPoint(IPAddress.Any, port);
m_listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
m_listener.Bind(theEnd);
Console.WriteLine("Binding to " +
theEnd.Address.ToString() + " on port " + theEnd.Port.ToString());
m_listener.Listen(20); //TODO: make this
configurable
Console.WriteLine("Now listening");
AsyncCallback callme = new AsyncCallback(AddWorkerSocket);
m_listener.BeginAccept(callme, m_listener);
}

private void AddWorkerSocket(IAsyncResult ar)
{
Console.WriteLine("Got a Connection");
Socket hold = (Socket)ar.AsyncState;
Socket work = hold.EndAccept(ar);
if (work.Connected)
{
Console.WriteLine("Accepted a connection from " +
work.RemoteEndPoint.ToString());
m_callBack(work);
}
AsyncCallback callMe = new AsyncCallback(AddWorkerSocket);
hold.BeginAccept(callMe, hold);
}

public void StopListening()
{
m_listener.Close();
}
}
 
M

Michael Rubinstein

I think you worry about wrong things. To begin with, why do initialize the
listener passing a delegate? You can certainly do so, but it will only make
your code more obscure.I was really wondering if anyone was familiar with the "best way" to stop
from this sort of loopthere must be a button or a switch on the front panel of your PC, or you can
just pull the AC cord. Seriously, whatever loops your program runs, or the
framework runs on your program behalf, will be exited once you stop the
service. If you want a graceful exit, then stop accepting new connections,
close all worker sockets, close the listener socket. The best way of
disconnecting connected clients is calling ShutDown() followed by
BeginDisconnect() end call socket.Close() from EndDisconnect().
BeginDisconnect()/EndDisconnect() are supported only on XP and higher. You
could get away with socket.Shutdown() / socket.Close() with proper error
interception in callback methods.
I would like this to become a window's service, so I want to listen for
incoming connections until the service is stopped.in my opinion this would require much cleaner code.

Michael

<
It does an infinite loop this way...

Does it bother you? Instead of closing the listening socket, you can put a
limit on the number of client connections and issue BeginAccept() only
until
that limit is reached. Normally you would close the listening socket only
after you have no clients connected and done with TCP.

Michael

I was hoping for an infinite loop, sort of. I would like this to
become a window's service, so I want to listen for incoming
connections until the service is stopped. I was really wondering if
anyone was familiar with the "best way" to stop from this sort of
loop. I have modified the code slightly so that when the service
stops, the list of sockets is looped through. While looping through
the sockets, I call Socket.Close() in order to try to clean up my
mess. It seems to work without throwing any exceptions, but I am just
wondering if this is the right way to do things.
Thanks again for your time and comments. Here is the modified code:
public delegate void ConnectionCallback(Socket sockMe);
public class Controller
{
private Listener m_listen;
private List<Socket> m_wokerList;
//need a connection
//private List<Connection> connectList;

public Controller()
{
m_wokerList = new List<Socket>(20); //TODO: make
this configurable
}

public void Start()
{
m_listen = new Listener(new
ConnectionCallback(this.AddSocketToList));
m_listen.AcceptNewConnections();
}

public void AddSocketToList(Socket sock)
{
Console.WriteLine("Got a socket and adding it to the list
of workers");
m_wokerList.Add(sock);
Console.WriteLine("There are now " +
m_wokerList.Count.ToString() + " sockets in the list.");
if (m_wokerList[m_wokerList.Count - 1].Connected)
{
Console.WriteLine("The last socket is connected to" +
m_wokerList[m_wokerList.Count - 1].RemoteEndPoint.ToString());
}
else
{
Console.WriteLine("The last socket is NOT connected");
}

}

public void Stop()
{
foreach (Socket closeSock in m_wokerList)
{
closeSock.Close();
}
m_listen.StopListening();
}
}
public class Listener
{
private Socket m_listener;
private ConnectionCallback m_callBack;

public Listener(ConnectionCallback callme)
{
m_callBack = callme;
}

public void AcceptNewConnections()
{
this.AcceptNewConnections(2200);
}

public void AcceptNewConnections(int port)
{
IPEndPoint theEnd = new IPEndPoint(IPAddress.Any, port);
m_listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
m_listener.Bind(theEnd);
Console.WriteLine("Binding to " +
theEnd.Address.ToString() + " on port " + theEnd.Port.ToString());
m_listener.Listen(20); //TODO: make this
configurable
Console.WriteLine("Now listening");
AsyncCallback callme = new AsyncCallback(AddWorkerSocket);
m_listener.BeginAccept(callme, m_listener);
}

private void AddWorkerSocket(IAsyncResult ar)
{
Console.WriteLine("Got a Connection");
Socket hold = (Socket)ar.AsyncState;
Socket work = hold.EndAccept(ar);
if (work.Connected)
{
Console.WriteLine("Accepted a connection from " +
work.RemoteEndPoint.ToString());
m_callBack(work);
}
AsyncCallback callMe = new AsyncCallback(AddWorkerSocket);
hold.BeginAccept(callMe, hold);
}

public void StopListening()
{
m_listener.Close();
}
}
 
D

darthghandi

I think you worry about wrong things. To begin with, why do initialize the
listener passing a delegate? You can certainly do so, but it will only make
your code more obscure.
So what should I worry about? I'm new at this and could use all the
help I can get.
I would like this to become a window's service, so I want to listen for
incoming connections until the service is stopped.
in my opinion this would require much cleaner code.
Do you have examples of what would be cleaner code? Since I am new at
this, I'm not aware of the mistakes I've made that you are
referencing.
Does anyone else have any suggestions?

Thanks for your time,
Chris
 

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