By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,939 Members | 1,541 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,939 IT Pros & Developers. It's quick & easy.

Stop listening on a socket?

P: n/a
Hi,
I'm currently working with sockets. I accept connections using
m_mySocket.Listen(BackLogCount); But when I want to stop listening, I
shutdown all my clients and call m_mySocket.Close(), but it always raise a
OnConnect event (actually, it calls the callback function as if there was a
new connection attempt) and I receive a ObjectDisposedException as soon as I
do m_mySocket.EndAccept.

Does anyone have any idea of what I could do about it? I would prefer not
to rely on exceptions as the normal process...

Thanks

ThunderMusic
Aug 28 '07 #1
Share this Question
Share on Google+
10 Replies


P: n/a
ThunderMusic wrote:
Hi,
I'm currently working with sockets. I accept connections using
m_mySocket.Listen(BackLogCount); But when I want to stop listening, I
shutdown all my clients and call m_mySocket.Close(), but it always raise a
OnConnect event (actually, it calls the callback function as if there was a
new connection attempt) and I receive a ObjectDisposedException as soon as I
do m_mySocket.EndAccept.

Does anyone have any idea of what I could do about it? I would prefer not
to rely on exceptions as the normal process...
I guess that depends on your definition of "normal process". :)

In some sense, the closure of the socket _is_ the exceptional case.
That is, normally the socket just sits there waiting for a connection
request. The exceptional case is when you close the socket.

In any case, AFAIK receiving the ObjectDisposedException _is_ the normal
way to detect socket closure in this situation. The outstanding i/o
BeginAccept i/o request you made needs to complete, and once you call
Socket.Close(), there's nothing else that EndAccept could do except
throw the exception that is specifically designed to indicate that
Socket.Close() has been called.

Exceptions aren't just for when something is broken. They are simply
ways to indicate the exceptional code path. It's true that errors cause
a lot of the exceptional cases, but I don't think that one should worry
about making sure that _only_ errors cause the exceptional cases.
Sometimes an exceptional case is an expected outcome, but is simply not
the usual outcome.

Pete
Aug 28 '07 #2

P: n/a

"Peter Duniho" <Np*********@NnOwSlPiAnMk.comwrote in message
news:13*************@corp.supernews.com...
ThunderMusic wrote:
>Hi,
I'm currently working with sockets. I accept connections using
m_mySocket.Listen(BackLogCount); But when I want to stop listening, I
shutdown all my clients and call m_mySocket.Close(), but it always raise
a OnConnect event (actually, it calls the callback function as if there
was a new connection attempt) and I receive a ObjectDisposedException as
soon as I do m_mySocket.EndAccept.

Does anyone have any idea of what I could do about it? I would prefer
not to rely on exceptions as the normal process...

I guess that depends on your definition of "normal process". :)

In some sense, the closure of the socket _is_ the exceptional case. That
is, normally the socket just sits there waiting for a connection request.
The exceptional case is when you close the socket.

In any case, AFAIK receiving the ObjectDisposedException _is_ the normal
way to detect socket closure in this situation. The outstanding i/o
BeginAccept i/o request you made needs to complete, and once you call
Socket.Close(), there's nothing else that EndAccept could do except throw
the exception that is specifically designed to indicate that
Socket.Close() has been called.

Exceptions aren't just for when something is broken. They are simply ways
to indicate the exceptional code path. It's true that errors cause a lot
of the exceptional cases, but I don't think that one should worry about
making sure that _only_ errors cause the exceptional cases. Sometimes an
exceptional case is an expected outcome, but is simply not the usual
outcome.

Pete
What I mean by "normal process" is I will always do everything I can do to
avoid an exception, but if I don't have any choice, I will catch the
exception... I mean... Is there a "cleaner" way of closing a socket? It's
perfectly normal and not an exceptional thing to reboot it's computer for
critical updates or any other reason... the application will be closed once
in a while... and most of all, I will have a functionnality in my app to
accept connections and stop accepting connections... I could do it by hand
with a state variable, but it would still be listening the port...

So, if I understand well, the only way to stop listening is to call "Stop"
on the socket and it will call the EndAccept callback... right?

Thanks

ThunderMusic
Aug 28 '07 #3

P: n/a
ThunderMusic wrote:
What I mean by "normal process" is I will always do everything I can do to
avoid an exception, but if I don't have any choice, I will catch the
exception...
My point is that exceptions are not necessarily something that need to
be avoided.
I mean... Is there a "cleaner" way of closing a socket?
No.
It's
perfectly normal and not an exceptional thing to reboot it's computer for
critical updates or any other reason...
I disagree. While it's not an error or otherwise a problem to need to
install a critical update (for example), it most certainly is an
"exceptional" situation. That is, it is not the usual state of affairs.
Most days you can get through without having to do that.

The _normal_ situation is to not have to install a critical update.
Once a month or so, you have an exceptional day, on which a critical
update needs to be installed.
the application will be closed once in a while...
But that's my point. Just because it's something that might have to
happen, that doesn't mean it's not an exceptional event.
and most of all, I will have a functionnality in my app to
accept connections and stop accepting connections... I could do it by hand
with a state variable, but it would still be listening the port...
Correct.
So, if I understand well, the only way to stop listening is to call "Stop"
on the socket and it will call the EndAccept callback... right?
If by "Stop" you actually mean "Close", then yes.

Pete
Aug 28 '07 #4

P: n/a

"Peter Duniho" <Np*********@NnOwSlPiAnMk.comwrote in message
news:13*************@corp.supernews.com...
ThunderMusic wrote:
>What I mean by "normal process" is I will always do everything I can do
to avoid an exception, but if I don't have any choice, I will catch the
exception...

My point is that exceptions are not necessarily something that need to be
avoided.
>I mean... Is there a "cleaner" way of closing a socket?

No.
>It's perfectly normal and not an exceptional thing to reboot it's
computer for critical updates or any other reason...

I disagree. While it's not an error or otherwise a problem to need to
install a critical update (for example), it most certainly is an
"exceptional" situation. That is, it is not the usual state of affairs.
Most days you can get through without having to do that.

The _normal_ situation is to not have to install a critical update. Once a
month or so, you have an exceptional day, on which a critical update needs
to be installed.
>the application will be closed once in a while...

But that's my point. Just because it's something that might have to
happen, that doesn't mean it's not an exceptional event.
>and most of all, I will have a functionnality in my app to accept
connections and stop accepting connections... I could do it by hand with
a state variable, but it would still be listening the port...

Correct.
>So, if I understand well, the only way to stop listening is to call
"Stop" on the socket and it will call the EndAccept callback... right?

If by "Stop" you actually mean "Close", then yes.

Pete
Yes by "Stop" I mean "Close"... Sorry, my bad... ;)

Ok... thanks, it helped me find a way... I was just stuck trying to find a
"normal" way like "close and don't do like if you are receiving a connection
attempt", but I will now just call Close and set a "flag" saying I'm
currently closing, so I won't call m_mySocket.EndAccept that would fail
anyway...

Thanks

ThunderMusic
Aug 28 '07 #5

P: n/a
ThunderMusic wrote:
Ok... thanks, it helped me find a way... I was just stuck trying to find a
"normal" way like "close and don't do like if you are receiving a connection
attempt", but I will now just call Close and set a "flag" saying I'm
currently closing, so I won't call m_mySocket.EndAccept that would fail
anyway...
You will want to verify that this is a reasonable way to write the code,
if that's the way you really want to do it.

In particular, while I don't know the specifics off the top of my head,
I suspect it's not a good idea to leave an unmatched BeginAccept
hanging. At the very least, it could leave a dangling reference
somewhere, preventing your Socket instance from being garbage-collected,
and for all I know there might actually be some unmanaged resource left
allocated that causes more issues that your run-of-the-mill memory leak.

One indication that my suspicion is correct is that you are not required
to keep a reference to the Socket instance for the async methods to
work. That is, you could do something like the following:

void Init()
{
Socket socket = new Socket();

socket.Bind(...);
socket.Listen(...);
socket.BeginAccept(AcceptCallback, socket);
}

void AcceptCallback(IAsyncResult ar)
{
Socket socket = (Socket)ar.AsyncState, socketAccepted;

socketAccepted = socket.EndAccept(ar);

// etc.
}

Note in the above that there is no explicit retention of the reference
to the Socket instance. So something else is keeping that reference for
you. If you don't call EndAccept(), that something else has no way to
know that you don't need the reference any more, and so it will keep
hanging on to it.

I really think that you are making way too much of the question of the
exception. The exception _is_ a "normal" thing, even though it is
exceptional (that is, doesn't happen in every case). I think you will
be much happier in the long run writing the code in the way that
Microsoft intends. That is, just include a "catch
(ObjectDisposedException)" clause in your callback method and handle it
appropriately.

It's not like you're doing anything truly different from that anyway,
with respect to the flag (you have to handle the case one way or the
other, regardless of how you detect it), and now you have this extra
flag lying around that you have to maintain. I'd be much more concerned
about adding cruft like that to my architecture than of handling an
exception.

Pete
Aug 28 '07 #6

P: n/a

"Peter Duniho" <Np*********@NnOwSlPiAnMk.comwrote in message
news:13*************@corp.supernews.com...
ThunderMusic wrote:
>Ok... thanks, it helped me find a way... I was just stuck trying to find
a "normal" way like "close and don't do like if you are receiving a
connection attempt", but I will now just call Close and set a "flag"
saying I'm currently closing, so I won't call m_mySocket.EndAccept that
would fail anyway...

You will want to verify that this is a reasonable way to write the code,
if that's the way you really want to do it.

In particular, while I don't know the specifics off the top of my head, I
suspect it's not a good idea to leave an unmatched BeginAccept hanging.
At the very least, it could leave a dangling reference somewhere,
preventing your Socket instance from being garbage-collected, and for all
I know there might actually be some unmanaged resource left allocated that
causes more issues that your run-of-the-mill memory leak.

One indication that my suspicion is correct is that you are not required
to keep a reference to the Socket instance for the async methods to work.
That is, you could do something like the following:

void Init()
{
Socket socket = new Socket();

socket.Bind(...);
socket.Listen(...);
socket.BeginAccept(AcceptCallback, socket);
}

void AcceptCallback(IAsyncResult ar)
{
Socket socket = (Socket)ar.AsyncState, socketAccepted;

socketAccepted = socket.EndAccept(ar);

// etc.
}

Note in the above that there is no explicit retention of the reference to
the Socket instance. So something else is keeping that reference for you.
If you don't call EndAccept(), that something else has no way to know that
you don't need the reference any more, and so it will keep hanging on to
it.

I really think that you are making way too much of the question of the
exception. The exception _is_ a "normal" thing, even though it is
exceptional (that is, doesn't happen in every case). I think you will be
much happier in the long run writing the code in the way that Microsoft
intends. That is, just include a "catch (ObjectDisposedException)" clause
in your callback method and handle it appropriately.

It's not like you're doing anything truly different from that anyway, with
respect to the flag (you have to handle the case one way or the other,
regardless of how you detect it), and now you have this extra flag lying
around that you have to maintain. I'd be much more concerned about adding
cruft like that to my architecture than of handling an exception.

Pete
Actually, even if I "cause the exception to happen", the EndAccept is not
called because I get an ObjectDisposedException... I call it on a disposed
object... So, I cannot call EndAccept at all because I need an ASyncResult
object to call it and when I receive this ASyncResult, the socket object is
already disposed (implicitly by Close).

Thanks

ThunderMusic
Aug 28 '07 #7

P: n/a
ThunderMusic wrote:
Actually, even if I "cause the exception to happen", the EndAccept is not
called because I get an ObjectDisposedException... I call it on a disposed
object... So, I cannot call EndAccept at all because I need an ASyncResult
object to call it and when I receive this ASyncResult, the socket object is
already disposed (implicitly by Close).
I don't understand. Are you saying you get the exception when casting
the AsyncState to a socket?

I was under the impression that you got the exception when calling
EndAccept() (this is the expected behavior).

Don't confuse the fact that the Socket has been disposed with the
question of whether the instance of the Socket is still being
referenced. Calling Dispose() on an object doesn't change whether that
object is referenced, and you still need to call EndAccept() to release
that reference.

If you're getting an exception elsewhere, then that's a different
matter. But assuming you're talking about an exception calling
EndAccept(), well...that's just a necessary exception. You need to call
EndAccept(), otherwise your Socket instance is still being referenced.

Pete
Aug 28 '07 #8

P: n/a

"Peter Duniho" <Np*********@NnOwSlPiAnMk.comwrote in message
news:13*************@corp.supernews.com...
ThunderMusic wrote:
>Actually, even if I "cause the exception to happen", the EndAccept is not
called because I get an ObjectDisposedException... I call it on a
disposed object... So, I cannot call EndAccept at all because I need an
ASyncResult object to call it and when I receive this ASyncResult, the
socket object is already disposed (implicitly by Close).

I don't understand. Are you saying you get the exception when casting the
AsyncState to a socket?

I was under the impression that you got the exception when calling
EndAccept() (this is the expected behavior).

Don't confuse the fact that the Socket has been disposed with the question
of whether the instance of the Socket is still being referenced. Calling
Dispose() on an object doesn't change whether that object is referenced,
and you still need to call EndAccept() to release that reference.

If you're getting an exception elsewhere, then that's a different matter.
But assuming you're talking about an exception calling EndAccept(),
well...that's just a necessary exception. You need to call EndAccept(),
otherwise your Socket instance is still being referenced.

Pete
Hi,
I may have been unclear... Actually, we can only call the EndAccept() in
the callback method because we need the IAsyncResult object as a
parameter... The thing is, when I call the
m_mySocket.EndAccept(asyncResult), I get an ObjectDisposedException,
because, I assume, Close() disposes the object implicitly... is it still the
expected behavior or is there a problem with it?

Thanks

ThunderMusic
Aug 29 '07 #9

P: n/a
ThunderMusic wrote:
I may have been unclear... Actually, we can only call the EndAccept() in
the callback method because we need the IAsyncResult object as a
parameter...
You can call EndAccept() at any time. Yes, you need an IAsyncResult.
However, this is returned by BeginAccept(), and of course you can always
take the IAsyncResult that's passed into the callback, store the
reference somewhere else, and call EndAccept() at a later time.

A server that wanted, for some reason, to process all accepted sockets
on a single thread might, for example, put the IAsyncResult instances
into a queue that was consumed by that single thread.

I'm not saying you'd want to do this. But the fact that you _can_ do
this affects what sort of requirements exist in the design of the async
API for Socket.
The thing is, when I call the
m_mySocket.EndAccept(asyncResult), I get an ObjectDisposedException,
because, I assume, Close() disposes the object implicitly... is it still the
expected behavior or is there a problem with it?
Close() does dispose the Socket. This is similar to Close() on other
class (e.g. FileStream), and any call to any method after calling
Close() will return that exception. So yes, I'd call that "expected
behavior". It's exceptional (thus the thrown exception), but expected.

I really don't think it's a problem to catch the
ObjectDisposedException. In fact, this should be a very reliable way to
identify a Socket that has been closed. You shouldn't get that
exception in any other case, because you should be using Close() to
dispose the socket.

Pete
Aug 29 '07 #10

P: n/a
Thanks a lot...

ThunderMusic
"Peter Duniho" <Np*********@NnOwSlPiAnMk.comwrote in message
news:13*************@corp.supernews.com...
ThunderMusic wrote:
>I may have been unclear... Actually, we can only call the EndAccept() in
the callback method because we need the IAsyncResult object as a
parameter...

You can call EndAccept() at any time. Yes, you need an IAsyncResult.
However, this is returned by BeginAccept(), and of course you can always
take the IAsyncResult that's passed into the callback, store the reference
somewhere else, and call EndAccept() at a later time.

A server that wanted, for some reason, to process all accepted sockets on
a single thread might, for example, put the IAsyncResult instances into a
queue that was consumed by that single thread.

I'm not saying you'd want to do this. But the fact that you _can_ do this
affects what sort of requirements exist in the design of the async API for
Socket.
>The thing is, when I call the m_mySocket.EndAccept(asyncResult), I get an
ObjectDisposedException, because, I assume, Close() disposes the object
implicitly... is it still the expected behavior or is there a problem
with it?

Close() does dispose the Socket. This is similar to Close() on other
class (e.g. FileStream), and any call to any method after calling Close()
will return that exception. So yes, I'd call that "expected behavior".
It's exceptional (thus the thrown exception), but expected.

I really don't think it's a problem to catch the ObjectDisposedException.
In fact, this should be a very reliable way to identify a Socket that has
been closed. You shouldn't get that exception in any other case, because
you should be using Close() to dispose the socket.

Pete

Aug 29 '07 #11

This discussion thread is closed

Replies have been disabled for this discussion.