> 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??
> And I can't just sit on receive and block the thread either.
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.
> ======================================================