Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / New Users / June 2007

Tip: Looking for answers? Try searching our database.

TcpClient

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
EdisonCPP - 25 May 2007 18:34 GMT
Hi,

I see that TcpClient.Connected only gets updated after
an I/O operation.  This stumps me.  I have a service
that listens for connections, and spawns a thread
for each connection to deal with client requests.
I maintian the thread as long as the service is running
and the socket is connected.  So I have something like
this:

//c++ pseudo code
void BasicThread(Object^ obect)
{
    while(running && client->Connected)
   {
         if(client->Available > 0)
         {
              //receive it, perform actions and respond
         }
    }
    client->Close();
    //do other cleanup
}

I've seen posts where several people say you just have to send or receive.
But if you image your server is a telnet server, then that wouldn't make
since.
What would I send to someone's telnet prompt JUST to make sure it's alive??
And I can't just sit on receive and block the thread either.  Isn't there
some
other way to check the socket like the old school select()?  This isn't a
telnet
server, but I don't want to be sending arbitrary stuff to the client either,
because
I am giving the ability that someone could talk to the server through a
terminal
program if necessary.  So pings are out.  I also can't check timers, clients
may
leave the client open for 24 hours without touching it, then start using it.
As is,
my client would maintain all clients that ever connected to them, threads
and all.

Thanks ahead of time,

Steven
Peter Duniho - 25 May 2007 19:11 GMT
> I see that TcpClient.Connected only gets updated after
> an I/O operation.

Yes.  Due to the nature of TCP, there is no way to know whether you are  
actually connected unless you try some i/o (in particular,  
sending...receiving isn't necessarily going to result in an error even if  
the connection has been broken).  Even if that i/o operation succeeds, a  
split second later your socket could be not connected and you'd have no  
way to know about it.  This is basic to TCP.

> This stumps me.  I have a service
> that listens for connections, and spawns a thread
[quoted text clipped - 8 lines]
> What would I send to someone's telnet prompt JUST to make sure it's  
> alive??

Why do you need to "make sure it's alive"?  One of the great things about  
TCP is that you can temporarily lose your connection, but as long as  
neither end tries to send any data, it doesn't matter.  The interruption  
in service doesn't cause a problem.

> And I can't just sit on receive and block the thread either.

Why can't you?  You state above that you have a separate thread for each  
client.  That's not a great way to handle your i/o, but as long as you  
aren't servicing a large number of clients, it should be fine.  More  
importantly, with one thread per client, and without anything to do until  
the client sends some data (or closes the connection), why is it bad for  
you to block on a call to Receive()?

> Isn't there some
> other way to check the socket like the old school select()?

The Winsock select() function wouldn't tell you whether the socket was  
connected either.  Are you asking about detecting connection state of the  
socket?  Or are you asking how to deal with non-blocking i/o?  The two  
questions are very different, and you seem to be mixing the two up.

For the record:

    1) The correct way to detect the closure of a TCP connection is to try  
to receive data, and if you receive 0 bytes, that means the connection has  
been closed.

    2) The correct way to handle a large number of simultaneous clients in  
.NET is to use the asynchronous method, starting with "Begin" and "End".  
This will allow you to handle arbitrarily large numbers of clients without  
having to create a new thread for each of them.

The above two techniques are orthogonal to each other and can be combined  
as necessary.  In particular, you should always be doing #1, and almost  
always should be doing #2.

Pete
EdisonCPP - 25 May 2007 20:50 GMT
Thanks for answering Pete.. see comments below.

>> I see that TcpClient.Connected only gets updated after
>> an I/O operation.
[quoted text clipped - 23 lines]
> neither end tries to send any data, it doesn't matter.  The interruption
> in service doesn't cause a problem.

Because if the client is completely finished, there's no reason to keep
threads open, and there are other things that need to be done in the
program after a user has "signed off".

I understand the way TCP works, but I've always been able to tell
in the past when the other side decided to end the connection.
(see below select() comments)

>> And I can't just sit on receive and block the thread either.
>
[quoted text clipped - 4 lines]
> the client sends some data (or closes the connection), why is it bad for
> you to block on a call to Receive()?

Well, that was just pseudo code, there are times when I need to send
things to the client on certain events.

>> Isn't there some
>> other way to check the socket like the old school select()?
[quoted text clipped - 3 lines]
> socket?  Or are you asking how to deal with non-blocking i/o?  The two
> questions are very different, and you seem to be mixing the two up.

Yes it will.  If you call select() and the socket has been gracefully closed
by the other end, then it will return > 0.  Create a socket via socket(),
and connect with connect(), then in a timer, or in a thread keep
checking fdRead with select(), if you close the other end of the socket,
you will go into select().  THEN you can call recv(), which will tell
you it's closed.  There IS a way to do it the old way.  In MFC you
get OnClose() instantly when the client closes their side of the connection.
Both of these methods don't tie up the thread, but let you know
when the other end has gracefully closed.

No, I'm not talking about non-blocking, same as straight forward old
CSocket and socket().

> For the record:
>
[quoted text clipped - 6 lines]
> This will allow you to handle arbitrarily large numbers of clients without
> having to create a new thread for each of them.

#2 is something I will research.  My thread works well because it lets me
keep up with "session" like data (not to be confused with internet), like a
user id who is connected, user states, and other connection specific
information.

> The above two techniques are orthogonal to each other and can be combined
> as necessary.  In particular, you should always be doing #1, and almost
> always should be doing #2.
>
> Pete
Peter Duniho - 25 May 2007 21:23 GMT
>> Why do you need to "make sure it's alive"? [...]
>
> Because if the client is completely finished, there's no reason to keep
> threads open, and there are other things that need to be done in the
> program after a user has "signed off".

If the client is completely finished, it should close the connection  
gracefully using shutdown() or similar API, which will be signaled to you  
by a successful completion of a receive, with zero bytes.

> I understand the way TCP works, but I've always been able to tell
> in the past when the other side decided to end the connection.
> (see below select() comments)

TCP does allow for telling when the other side decides to close the  
connection.  But it doesn't do so by providing you a way to poll for the  
"connectedness" of the socket.

> Well, that was just pseudo code, there are times when I need to send
> things to the client on certain events.

That's fine.  You just can't use the thread waiting on the Receive()  
method to do the sending, since it's blocked.  Do the send from a  
different thread.

>> The Winsock select() function wouldn't tell you whether the socket was
>> connected either.

> Yes it will.  If you call select() and the socket has been gracefully  
> closed by the other end, then it will return > 0.

It also returns a value greater than zero for successful receives,  
connections, accepts, etc.  All that select() is telling you is that some  
sort of i/o event happened.  It does NOT tell you whether the socket is  
connected or not.  For example, when using select() if the remote end  
closes the connection, select() will still return a number greater than  
zero, and indicate that the socket is ready for you to call recv() on it.  
That call to recv() will succeed, but with a return value of 0 bytes read.

In other words, select() isn't telling you the connected state of the  
socket, receive() is.

> Create a socket via socket(),
> and connect with connect(), then in a timer, or in a thread keep
> checking fdRead with select(), if you close the other end of the socket,
> you will go into select().

Why would you poll AND use select()?  That's really broken code that does  
that.  The whole point of select() is that you can hand it a bunch of  
sockets and have it block.  If all you're doing is polling, you might as  
well just set the socket(s) to non-blocking and poll them directly.  Using  
socket() in that scenario buys you nothing.

> THEN you can call recv(), which will tell you it's closed.

Yes.  As I wrote above, it is the recv() method that tells you whether the  
socket is closed or not.  The select() method doesn't do that, and you  
don't need to call it at all to get the information that recv() gives you.

> There IS a way to do it the old way.

And you can do it in the new way too, and it works just like it works in  
the old way.

> In MFC you get OnClose() instantly when the client closes their side of  
> the connection.
> Both of these methods don't tie up the thread, but let you know
> when the other end has gracefully closed.

Only because they are both waiting for some i/o.  I don't know how MFC  
implements its OnClose() method, but Winsock provides for a wide variety  
of mechanisms to deal with notification of socket i/o events.  But in  
every case, *somewhere* something is waiting for the i/o to happen.  And  
the detection of the closure of the connection *always* involves the i/o  
actually occuring and being detected as a closure of the connection.

Whether this is done via a call to receive() that returns zero bytes, or  
some lower-level mechanism that looks at the underlying FIN IP datagram  
and sends an FD_CLOSE message (WSAAsyncSelect()) or sets an event  
(WSAEventSelect()) or does something else, the closure is not detected  
unless there's some i/o that signals the closure.

> No, I'm not talking about non-blocking, same as straight forward old
> CSocket and socket().

Um...I can't speak for CSocket, having never used MFC's implementation,  
but non-blocking and socket() are not mutually exclusive at all.  In fact,  
most well-written socket applications use the socket returned by socket()  
with non-blocking semantics.

You brought up select(), which should only be used with non-blocking  
sockets.  It makes no sense to use it with blocking sockets, since there's  
no guarantee that after select() returns an indication that a socket is  
ready for reading or writing, that reading or writing can actually occur  
successfully.  With a blocking socket, you could wind up blocking on the  
send() or recv() function call right after returning from select().

If you're not talking about non-blocking sockets, I don't understand why  
you mentioned the select() function.

> #2 is something I will research.  My thread works well because it lets me
> keep up with "session" like data (not to be confused with internet),  
> like a
> user id who is connected, user states, and other connection specific
> information.

There's no reason you can't do things the way you're doing them now, so  
long as you understand that dedicating a thread to each connection won't  
scale very well.  Performance will suffer, and you'll reach the maximum  
number of threads possible long before you reach the maximum number of  
clients a socket-based server can actually handle.  But for a small number  
of clients, if it simplifies the overall code you may find it's better to  
just use a thread-per-connection design.

But even so, it's important to understand what's possible and what's not,  
and what's an appropriate use of the API.  You should never poll, and you  
cannot rely on a simple test to detect whether a socket is connected.  
Without i/o there's no way to know if the TCP connection is still  
connected.  None of the various Windows APIs that support TCP provide  
connectedness information without some i/o happening.

Pete
Charles Wang[MSFT] - 05 Jun 2007 02:59 GMT
Hi Edison,
As far as I know, although select() method may get the close signal from
the other side, it is not always reliable. After use it, you still need to
use send() or recv() to check if the return value is -1.

I think that Pete's answer is detailed and helpful. Could you please let us
know if you need further assistance on this issue?

Have a good day!

Best regards,
Charles Wang
Microsoft Online Community Support
=====================================================
Get notification to my posts through email? Please refer to:
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications

If you are using Outlook Express, please make sure you clear the check box
"Tools/Options/Read: Get 300 headers at a time" to see your reply promptly.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
======================================================
When responding to posts, please "Reply to Group" via
your newsreader so that others may learn and benefit
from this issue.
======================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
======================================================
Steven Edison - 07 Jun 2007 15:54 GMT
Yes, his reply lead to a usable solution.  Thanks to both of you.

Steven

> Hi Edison,
> As far as I know, although select() method may get the close signal from
[quoted text clipped - 38 lines]
> rights.
> ======================================================

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.