PC Review


Reply
Thread Tools Rate Thread

Closing socket during async Receive

 
 
Dinsdale
Guest
Posts: n/a
 
      19th Jun 2006
I am trying to write a Tcp "Server" that opens a class that wraps a tcp
socket when a new connection is made (Listener.AcceptSocket()).
Everything is going swimmingly except when I try to close the socket
during a read and I get the following error:

<error_msg>
An unhandled exception of type 'System.Net.Sockets.SocketException'
occurred in system.dll

Additional information: The I/O operation has been aborted because of
either a thread exit or an application request
</error_msg>

The following is the delegate function for the BeginReceive call:

private void ReadStream(IAsyncResult ar)
{
if(IsAvailable)
{
lock(_socClient) //*** - Futile attempt to stop the exception
{

int intByteCount = _socClient.EndReceive(ar);//**** - THIS
IS WHERE I GET MY EXCEPTION

if(intByteCount > 0)
{
_tmrTimeout.Stop();

ProcessInput(_abytBuffer, intByteCount);//Adds any
ASCII text to a string buffer

if(IsAvailable)
{
_socClient.BeginReceive(_abytBuffer,0,
BUFFER_LENGTH,SocketFlags.None,
_acbBeginReadCallback,_socClient);
}
_tmrTimeout.Start();
}
else
{
Close(true);
}
}
}
else
{
Close(false);
}
}


My shut down routine looks like this:

public bool IsAvailable
{
get
{
if((!_bShutdown) && (_socClient != null) &&
_socClient.Connected)
{
return true;
}
else
{
return false;
}
}
}

public void Close(bool bSendStatusUpdate)
{
if(IsAvailable)
{
lock(_socClient)
{
_bShutdown = true; //An attempt to indicate what is going
on... SO didn't work

_socClient.Shutdown(SocketShutdown.Both);
_socClient.Close();
}
//_socClient = null;
}
_tmrTimeout.Stop();

if(bSendStatusUpdate)
{
OnClientStatusChanged(new ClientStatusChangedEventArgs(
CommStatusType.CLOSED,RemoteEndPoint,"Closed"));
}
}

#region IDisposable Members

public void Dispose()
{
if(IsAvailable)
{
Close(false);
}
}

#endregion

I thought that maybe I can manually call the EndReceive function from
the Close() routine but I cannot declare a IAsyncResult object. Any
suggestions to close the connection would be great.

Once again, thank you to the Google community for saving my behind.
I'll try to answer a couple of other messages in return.

Cheers,

Russ

 
Reply With Quote
 
 
 
 
Barry Kelly
Guest
Posts: n/a
 
      19th Jun 2006
"Dinsdale" <(E-Mail Removed)> wrote:

> I am trying to write a Tcp "Server" that opens a class that wraps a tcp
> socket when a new connection is made (Listener.AcceptSocket()).
> Everything is going swimmingly except when I try to close the socket
> during a read and I get the following error:
>
> <error_msg>
> An unhandled exception of type 'System.Net.Sockets.SocketException'
> occurred in system.dll
>
> Additional information: The I/O operation has been aborted because of
> either a thread exit or an application request
> </error_msg>

[snip]
> int intByteCount = _socClient.EndReceive(ar);//**** - THIS
> IS WHERE I GET MY EXCEPTION

[snip]
> I thought that maybe I can manually call the EndReceive function from
> the Close() routine but I cannot declare a IAsyncResult object. Any
> suggestions to close the connection would be great.


From my somewhat limited experience with async sockets, there are two
things interacting here. First, interrupting a blocking call like
Receive (if you weren't using async sockets) from another thread would
result in an exception being thrown - that just happens to be how the
..NET Socket class communicates the interruption at the Winsock level.

The second thing is that exceptions thrown from an asynchronous
operation get delayed until the call to the End* method. So, you only
get notification of the interruption when you call EndReceive().

Basically, what you're seeing is normal behaviour, AFAIK. You've got to
be prepared to catch the exception thrown when and where you call
EndReceive().

> Once again, thank you to the Google community for saving my behind.
> I'll try to answer a couple of other messages in return.


Believe it or not, this is the Microsoft community These newsgroups
are hosted on Microsoft's servers (NNTP on news.microsoft.com), and get
mirrored to Usenet. Google Groups is a web-based interface to Usenet (as
well as having its own, non-Usenet, groups).

-- Barry

--
http://barrkel.blogspot.com/
 
Reply With Quote
 
Dinsdale
Guest
Posts: n/a
 
      19th Jun 2006
> Believe it or not, this is the Microsoft community These newsgroups
> are hosted on Microsoft's servers (NNTP on news.microsoft.com), and get
> mirrored to Usenet.


Nooooooo! Well, okay, thank you to the evil empire and it's minions of
darkness (of which I myself am a sergeant).

> Basically, what you're seeing is normal behaviour, AFAIK. You've got to
> be prepared to catch the exception thrown when and where you call
> EndReceive().

So if I understand this correctly, there will be an exception -
REGARDLESS of what I do - when I close the socket and there was a
BeginReceive call made. I find this odd and frustrating, but I guess it
is consistent with other async. functionality (i.e. when you stop a
thread). I just don't like to write code that is EXPECTED to use an
exception block. This is normal behaviour, not an 'exception' to the
regular functioning of a control (IMHO).

Thanks for the help Barry!

Russ


Barry Kelly wrote:
> "Dinsdale" <(E-Mail Removed)> wrote:
>
> > I am trying to write a Tcp "Server" that opens a class that wraps a tcp
> > socket when a new connection is made (Listener.AcceptSocket()).
> > Everything is going swimmingly except when I try to close the socket
> > during a read and I get the following error:
> >
> > <error_msg>
> > An unhandled exception of type 'System.Net.Sockets.SocketException'
> > occurred in system.dll
> >
> > Additional information: The I/O operation has been aborted because of
> > either a thread exit or an application request
> > </error_msg>

> [snip]
> > int intByteCount = _socClient.EndReceive(ar);//**** - THIS
> > IS WHERE I GET MY EXCEPTION

> [snip]
> > I thought that maybe I can manually call the EndReceive function from
> > the Close() routine but I cannot declare a IAsyncResult object. Any
> > suggestions to close the connection would be great.

>
> From my somewhat limited experience with async sockets, there are two
> things interacting here. First, interrupting a blocking call like
> Receive (if you weren't using async sockets) from another thread would
> result in an exception being thrown - that just happens to be how the
> .NET Socket class communicates the interruption at the Winsock level.
>
> The second thing is that exceptions thrown from an asynchronous
> operation get delayed until the call to the End* method. So, you only
> get notification of the interruption when you call EndReceive().
>
> Basically, what you're seeing is normal behaviour, AFAIK. You've got to
> be prepared to catch the exception thrown when and where you call
> EndReceive().
>
> > Once again, thank you to the Google community for saving my behind.
> > I'll try to answer a couple of other messages in return.

>
> Believe it or not, this is the Microsoft community These newsgroups
> are hosted on Microsoft's servers (NNTP on news.microsoft.com), and get
> mirrored to Usenet. Google Groups is a web-based interface to Usenet (as
> well as having its own, non-Usenet, groups).
>
> -- Barry
>
> --
> http://barrkel.blogspot.com/


 
Reply With Quote
 
Mehdi
Guest
Posts: n/a
 
      19th Jun 2006
On 19 Jun 2006 09:56:57 -0700, Dinsdale wrote:

> Once again, thank you to the Google community for saving my behind.
> I'll try to answer a couple of other messages in return.


Barry already gave you a good answer. What you're seeing is the normal
behaviour and this exception allows you to know that the socket has been
closed and that you should give up trying to do any further processing.

I just wanted to point out, since you're obvioulsy new to usenet, that this
is not the Google community here but, as Barry pointed out, the usenet
community. There are many web sites that allow you to access usenet
newsgroups from your web browser and Google is just one of them. I suggest
that you get yourself a usenet newsgroup reader software such as Outlook
Express, 40tude Dialog, Forte Agent, etc and use it to read and post on
usenet instead of using Google. It's a lot easier to follow a conversation,
post and browse a newsgroup using a specialized software rather than using
Google's web interface. And you'll quickly find yourself hooked to usenet
and start reading and posting on your favorite newsgroups everyday, which
will allow you to not feel guilty of always asking questions without
contributing (note though that people asking questions here are absolutely
not expected to contribute in return although it's always a good thing when
the community grows).
 
Reply With Quote
 
Barry Kelly
Guest
Posts: n/a
 
      19th Jun 2006
"Dinsdale" <(E-Mail Removed)> wrote:

> So if I understand this correctly, there will be an exception -
> REGARDLESS of what I do - when I close the socket and there was a
> BeginReceive call made. I find this odd and frustrating, but I guess it
> is consistent with other async. functionality (i.e. when you stop a
> thread). I just don't like to write code that is EXPECTED to use an
> exception block. This is normal behaviour, not an 'exception' to the
> regular functioning of a control (IMHO).


The proper way to close the connection is to call Shutdown() on the
other thread, not Close(). That way you get the standard close condition
for the connection (i.e. a read of 0 bytes). For example:

---8<---
using System;
using System.Threading;
using System.Net.Sockets;
using System.Net;

class App
{
static void Main(string[] args)
{
TcpListener server = new TcpListener(IPAddress.Loopback, 2000);
server.Start();
try
{
Console.WriteLine("Listening on {0}", server.LocalEndpoint);
using (Socket client = server.AcceptSocket())
{
Console.WriteLine("Accepted: {0}",
client.RemoteEndPoint);

ThreadPool.QueueUserWorkItem(delegate
{
Console.WriteLine("Going to close in 1 second.");
Thread.Sleep(TimeSpan.FromSeconds(1));
Console.WriteLine("Closing...");
client.Shutdown(SocketShutdown.Both);
});

byte[] buffer = new byte[512];
int read = client.Receive(buffer);
Console.WriteLine("Read {0} bytes.", read);
}
}
finally
{
server.Stop();
}
}
}
--->8---

-- Barry

--
http://barrkel.blogspot.com/
 
Reply With Quote
 
Dinsdale
Guest
Posts: n/a
 
      19th Jun 2006
>What you're seeing is the normal
> behaviour and this exception allows you to know that the socket has been
> closed and that you should give up trying to do any further processing.


After re-reading the documentation, I see your point. when EndReceive
returns 0 bytes, it's a REMOTE host disconnect. I expected the same
behaviour on local endpoint disconnects.

Thank you for clarifying the usenet thing (Barry and Mehdi). I will be
sure to look into other usenet clients.

Cheers,
Russ

Mehdi wrote:
> On 19 Jun 2006 09:56:57 -0700, Dinsdale wrote:
>
> > Once again, thank you to the Google community for saving my behind.
> > I'll try to answer a couple of other messages in return.

>
> Barry already gave you a good answer. What you're seeing is the normal
> behaviour and this exception allows you to know that the socket has been
> closed and that you should give up trying to do any further processing.
>
> I just wanted to point out, since you're obvioulsy new to usenet, that this
> is not the Google community here but, as Barry pointed out, the usenet
> community. There are many web sites that allow you to access usenet
> newsgroups from your web browser and Google is just one of them. I suggest
> that you get yourself a usenet newsgroup reader software such as Outlook
> Express, 40tude Dialog, Forte Agent, etc and use it to read and post on
> usenet instead of using Google. It's a lot easier to follow a conversation,
> post and browse a newsgroup using a specialized software rather than using
> Google's web interface. And you'll quickly find yourself hooked to usenet
> and start reading and posting on your favorite newsgroups everyday, which
> will allow you to not feel guilty of always asking questions without
> contributing (note though that people asking questions here are absolutely
> not expected to contribute in return although it's always a good thing when
> the community grows).


 
Reply With Quote
 
Barry Kelly
Guest
Posts: n/a
 
      19th Jun 2006
"Dinsdale" <(E-Mail Removed)> wrote:

> >What you're seeing is the normal
> > behaviour and this exception allows you to know that the socket has been
> > closed and that you should give up trying to do any further processing.

>
> After re-reading the documentation, I see your point. when EndReceive
> returns 0 bytes, it's a REMOTE host disconnect. I expected the same
> behaviour on local endpoint disconnects.


Calling Shutdown() instead of Close() will also cause EndReceive to
return 0 bytes, for a LOCAL host disconnect. Ideally, you should call
Close() on the thread that logically "owns" the underlying socket.

-- Barry

--
http://barrkel.blogspot.com/
 
Reply With Quote
 
Dinsdale
Guest
Posts: n/a
 
      23rd Jun 2006
I call both Shutdown() and Close():

if(IsAvailable)
{
lock(_socClient)
{
_bShutdown = true;
_socClient.Shutdown(SocketShutdown.Both);
_socClient.Close();
}
}

Is the call to close unnecessary?

Russ


Barry Kelly wrote:
> "Dinsdale" <(E-Mail Removed)> wrote:
>
> > >What you're seeing is the normal
> > > behaviour and this exception allows you to know that the socket has been
> > > closed and that you should give up trying to do any further processing.

> >
> > After re-reading the documentation, I see your point. when EndReceive
> > returns 0 bytes, it's a REMOTE host disconnect. I expected the same
> > behaviour on local endpoint disconnects.

>
> Calling Shutdown() instead of Close() will also cause EndReceive to
> return 0 bytes, for a LOCAL host disconnect. Ideally, you should call
> Close() on the thread that logically "owns" the underlying socket.
>
> -- Barry
>
> --
> http://barrkel.blogspot.com/


 
Reply With Quote
 
Dinsdale
Guest
Posts: n/a
 
      23rd Jun 2006
Ideally, you should call
> > Close() on the thread that logically "owns" the underlying socket.


I have moved the Close() call into the delegate function that handles
the BeginReceive calls and that eliminated the exception. The Close()
function is only called after the EndReceive() call returns 0 bytes,
instead of me forcing it immediately aftger the shutdown call.

if(intByteCount > 0)
{
//...Normal Processing
}
Else
{
Close(true);
_socClient.Close();
}

Thanks for your help Barry, I was POSITIVE that there was a way to do
this without having to rely on an exception.

Russ

Dinsdale wrote:
> I call both Shutdown() and Close():
>
> if(IsAvailable)
> {
> lock(_socClient)
> {
> _bShutdown = true;
> _socClient.Shutdown(SocketShutdown.Both);
> _socClient.Close();
> }
> }
>
> Is the call to close unnecessary?
>
> Russ
>
>
> Barry Kelly wrote:
> > "Dinsdale" <(E-Mail Removed)> wrote:
> >
> > > >What you're seeing is the normal
> > > > behaviour and this exception allows you to know that the socket has been
> > > > closed and that you should give up trying to do any further processing.
> > >
> > > After re-reading the documentation, I see your point. when EndReceive
> > > returns 0 bytes, it's a REMOTE host disconnect. I expected the same
> > > behaviour on local endpoint disconnects.

> >
> > Calling Shutdown() instead of Close() will also cause EndReceive to
> > return 0 bytes, for a LOCAL host disconnect. Ideally, you should call
> > Close() on the thread that logically "owns" the underlying socket.
> >
> > -- Barry
> >
> > --
> > http://barrkel.blogspot.com/


 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Async socket EnzoA Microsoft VC .NET 1 10th May 2005 01:51 PM
after opening socket, sending data then closing socket 3000 times i get "Only one usage of each socket address" Daniel Microsoft Dot NET 1 15th Mar 2005 11:37 AM
after opening socket, sending data then closing socket 3000 times i get "Only one usage of each socket address" Daniel Microsoft Dot NET Framework 3 12th Feb 2005 02:53 PM
Async socket IO Alexander Muylaert Microsoft C# .NET 2 24th Oct 2004 11:20 AM
Async Socket IO Pete Davis Microsoft C# .NET 2 24th Mar 2004 10:16 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 04:49 AM.