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

Closing socket during async Receive

P: n/a
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

Jun 19 '06 #1
Share this Question
Share on Google+
8 Replies


P: n/a
"Dinsdale" <ru********@gmail.com> 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/
Jun 19 '06 #2

P: n/a
> 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" <ru********@gmail.com> 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/


Jun 19 '06 #3

P: n/a
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).
Jun 19 '06 #4

P: n/a
"Dinsdale" <ru********@gmail.com> 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/
Jun 19 '06 #5

P: n/a
>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).


Jun 19 '06 #6

P: n/a
"Dinsdale" <ru********@gmail.com> 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/
Jun 19 '06 #7

P: n/a
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" <ru********@gmail.com> 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/


Jun 23 '06 #8

P: n/a
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" <ru********@gmail.com> 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/


Jun 23 '06 #9

This discussion thread is closed

Replies have been disabled for this discussion.