*Experts* Bucky Posted January 9, 2004 *Experts* Posted January 9, 2004 In writing code to handle the listening and connection-accepting of a Socket instance, I've run into a snag after calling BeginAccept. After calling BeginAccept, I want to be able to cancel the calling of my callback function and essentially stop the Socket from listening before it actually receives a connection request. When a connection request does come, the Socket accepts it, receives from it, and closes it fine, but I'd like to be able to stop the Socket from listening before a connection is requested. GavinO suggested a very creative kludge that invoves creating a new Socket and connecting with listening one so that the connection would be made (behind the scenes) and then successfully closed right away. Needless to say, I'm hoping there's a more elegant way. :) Oh, and this is the code I'm using to start the accept callback: IAsyncResult beginAcceptResult; beginAcceptResult = listenSocket.BeginAccept(new AsyncCallback(ListenCallback), null); Thanks. Quote "Being grown up isn't half as fun as growing up These are the best days of our lives" -The Ataris, In This Diary
*Gurus* divil Posted January 9, 2004 *Gurus* Posted January 9, 2004 What about the Shutdown and/or Close methods? Quote MVP, Visual Developer - .NET Now you see why evil will always triumph - because good is dumb. My free .NET Windows Forms Controls and Articles
*Experts* Bucky Posted January 11, 2004 Author *Experts* Posted January 11, 2004 I have tried each and both of these methods, with no success. Calling Shutdown first raises a SocketError when I try to Close or dispose of the Socket, quote, "A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied". Just calling Close raises an InvalidOperationException that only says "AcceptCallback", and it points to a location in the disassembly, though Close is what causes it. Quote "Being grown up isn't half as fun as growing up These are the best days of our lives" -The Ataris, In This Diary
*Gurus* divil Posted January 11, 2004 *Gurus* Posted January 11, 2004 Are you sure the exception isn't being thown by EndAccept when you call it from your async handler, because you've just shut down the socket? In which case you'd want to just trap the exception and move on. Quote MVP, Visual Developer - .NET Now you see why evil will always triumph - because good is dumb. My free .NET Windows Forms Controls and Articles
*Experts* Bucky Posted January 11, 2004 Author *Experts* Posted January 11, 2004 EndAccept never gets a chance to be called. When calling Shutdown, the error points to the line listenSocket = null; When calling Close, there is only a disassembly location for the error. Quote "Being grown up isn't half as fun as growing up These are the best days of our lives" -The Ataris, In This Diary
Rodenberg Posted February 7, 2004 Posted February 7, 2004 You could always cheat and set a flag to specify whether the code within the EndInvoke is executed or not. private bool flag = true; private void EndCallback(IAsyncResult result){ if(flag){ ..... execute code.... } } Quote
*Experts* Bucky Posted February 7, 2004 Author *Experts* Posted February 7, 2004 Yes, but then I cannot call Close and then Listen on the same port, because a socket will still be bound to that port. Quote "Being grown up isn't half as fun as growing up These are the best days of our lives" -The Ataris, In This Diary
dmartz Posted February 28, 2004 Posted February 28, 2004 I am experiencing the same problem. It's really strange, has anyone made any advances in this? Quote
MNimmo Posted February 25, 2005 Posted February 25, 2005 How to cancel asynchronous socket accept calls. Right firstly, Bucky. When you call close on an accepting socket, the asynchronous request is triggered as completed with an invalid socket, therefore when your program calls EndAccept it tries to access a non-existant socket and causes the EndAccept exception. As Rodenburg suggested a flag can be used to catch when this occurs so that you don't call EndAccept in these cases. However there is another way. The IAsyncResult parameter that is passed to the function contains the data about the socket that accepts the connection. I.e. A member of IAsyncResult contains the socket returned by EndAccept. This member is AsyncState. If you cast this to a socket, then you can look at the underlining handle for the socket to see if it is valid (>= 0) or invalid (-1). If the handle is -1 then the accept call was cancelled. Example.... private void AcceptSmtp(IAsyncResult ar) { Socket test = (Socket)ar.AsyncState; // Cast the result to a socket. if (test.Handle.ToInt32() == -1) // Check if the handle is invalid. { return; // Exit as the call was cancelled. } // If we get here then this is an actual accept. Socket client = smtpListener.EndAccept(ar); // Get the socket. ........ } Hope this helps you all, Mike Nimmo. Quote
MNimmo Posted February 26, 2005 Posted February 26, 2005 As a quick update, it appears that EndAccept must be called within the asynchronous function but if the socket is invalid then you can call EndAccept within a trap. Quote
Diesel Posted March 1, 2005 Posted March 1, 2005 (edited) Actually, I've never encountered that problem. To close down the listening socket: if (serverThread != null) { if (serverThread.IsAlive) { if (listeningSocket.Connected) { listeningSocket.Shutdown(System.Net.Sockets.SocketShutdown.Both); listeningSocket.Close(); } serverThread.Abort(); } } When calling BeginAccept, why do you save the AsyncResult? The AsyncResult is passed to the EventHandling function. Try: private static System.Threading.ManualResetEvent allDone = new System.Threading.ManualResetEvent(false); while (true) { allDone.Reset(); listeningSocket.BeginAccept(new AsyncCallback(AcceptCallback), null); allDone.WaitOne(); } private void AcceptCallback(IAsyncResult ar) { allDone.Set(); socket = listeningSocket.EndAccept(ar); } Edited March 1, 2005 by Diesel Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.