TcpClient

E

EdisonCPP

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
 
P

Peter Duniho

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
for each connection to deal with client requests.

[...]

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??

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
 
E

EdisonCPP

Thanks for answering Pete.. see comments below.

Peter Duniho said:
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
for each connection to deal with client requests.

[...]

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??

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.

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)
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()?

Well, that was just pseudo code, there are times when I need to send
things to the client on certain events.
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.

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:

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.

#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.
 
P

Peter Duniho

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.
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
 
C

Charles Wang[MSFT]

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.
======================================================
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top