Re: TcpClient
- From: "Peter Duniho" <NpOeStPeAdM@xxxxxxxxxxxxxxxx>
- Date: Fri, 25 May 2007 13:23:17 -0700
On Fri, 25 May 2007 12:50:04 -0700, EdisonCPP <EdisonCPP@xxxxxxxxxxxxxxxxx> wrote:
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
.
- References:
- TcpClient
- From: EdisonCPP
- Re: TcpClient
- From: Peter Duniho
- Re: TcpClient
- From: EdisonCPP
- TcpClient
- Prev by Date: Re: Best first .NET book for experienced programmer?
- Next by Date: Re: Inheritance question
- Previous by thread: Re: TcpClient
- Next by thread: Inheritance question
- Index(es):
Relevant Pages
|