You are not logged in.

Dear visitor, welcome to QtForum.org. If this is your first visit here, please read the Help. It explains in detail how this page works. To use all features of this page, you should consider registering. Please use the registration form, to register here or read more information about the registration process. If you are already registered, please login here.

Tom

Trainee

  • "Tom" is male
  • "Tom" started this thread

Posts: 48

Location: Darmstadt, Germany

  • Send private message

1

Monday, August 16th 2004, 10:48am

How does server notice Client disconnection?

Hi all,

I am using QSocket for Client<->Server communication. When the server fails, the client gets a notice, but how does the server notice a client disconnecting?

Does anyone know?

Any help appreciated.

Many thanks in advance.

Ciao
Tom
---
There are only 10 types of people in the world:
Those who understand binary and those who don't.
---

2

Monday, August 16th 2004, 3:29pm

When you use TCP, it's easy.
If a socket gets closed in the proper way, a message is sent to the other side to say: "Hey, I'm gone, see you later".

This can be done by the server, but also the client. So when the client closes it's connection, the server will see this.

I don't really know how this is done with UDP though.


But, problems will occure when the socket isn't closed in the proper way. With this I mean, the client didn't say to the server "I'm gone". This can happen for example when the connection of the client pc is suddenly broken.

There are several techniques to work around this problem.

For example, regularly probe the client (send something to it) to see if it's still alive.

But the best way to solve it, is in my opinion, to work with timeouts.
If you're sending something, and it takes too long to send a block of data, create a send timeout, and close the socket.
If you're waiting for input, and for a while, the client didn't send anything, create a read timeout, and close the socket.

This is how most ftp, http, nntp, etc... servers work.
The client just has to reconnect again.

Tom

Trainee

  • "Tom" is male
  • "Tom" started this thread

Posts: 48

Location: Darmstadt, Germany

  • Send private message

3

Tuesday, August 17th 2004, 10:39am

@tbscope

that's what I thought, too. By the way, I am using TCP. When the server crashes some kind of notification is send to the clients and then they try reconnecting. I thought that there might be a similiar way if a client crashes...I cannot create too much traffic, that's the problem.

Thanks for your help.

Ciao
Tom
---
There are only 10 types of people in the world:
Those who understand binary and those who don't.
---

  • "wysota" is male

Posts: 4,276

Location: Warsaw, POLAND

  • Send private message

4

Tuesday, August 17th 2004, 11:55am

Quoted

Originally posted by tbscope
When you use TCP, it's easy.
If a socket gets closed in the proper way, a message is sent to the other side to say: "Hey, I'm gone, see you later".

This can be done by the server, but also the client. So when the client closes it's connection, the server will see this.


It has to be done by BOTH the client AND the server... TCP is a two way connection, both ends have to close their read and write handlers for a connection to close properly (normally done by the shutdown(2) function - or by close(2), which closes both handlers at once).

Quoted


I don't really know how this is done with UDP though.


UDP isn't a connection protocol - you don't have a "connection" here, so you don't have to (and even don't have the ability to) close it. UDP is datagram based, it just sends some data, but doesn't assure that it reaches destination at all, and even if it does, it doesn't assure that datagrams don't get mixed, cut, reordered...

Quoted


But, problems will occure when the socket isn't closed in the proper way. With this I mean, the client didn't say to the server "I'm gone". This can happen for example when the connection of the client pc is suddenly broken.

It works the other way round too...


Quoted


For example, regularly probe the client (send something to it) to see if it's still alive.


This is called keep-alive, it's used with connections which last very long but rarely transmit any information.

Quoted


But the best way to solve it, is in my opinion, to work with timeouts.
If you're sending something, and it takes too long to send a block of data, create a send timeout, and close the socket.


The thing is, what does "too long" mean? You don't have any info about the distance between the two ends and neither about the way packets get transmitted through the net. That timeout should be about several minutes and then this solution is simmilar to sending keep-alive packets (which is by way a much better solution than closing the connection without checking the host).

Quoted

This is how most ftp, http, nntp, etc... servers work.
The client just has to reconnect again.

Yea, but these are very specific, they are under a heavy load and can't afford waiting too long... especially http and nntp differ, because they are not really connection based - the client requests something, it receives some info and the "connection" may close, if it breaks, nothing bad happens, the client can reconnect again and continue from a point it lost connection, they are not exactly session-based. For session-based services, you should additionally provide a way to store a session and continue from such "milestone" point, syncing such points is a good way to test the connection.

  • "wysota" is male

Posts: 4,276

Location: Warsaw, POLAND

  • Send private message

5

Tuesday, August 17th 2004, 11:59am

Quoted

Originally posted by Tom
I thought that there might be a similiar way if a client crashes...I cannot create too much traffic, that's the problem.


If a client crashes, the server sould receive a EOF mark ('\0' for POSIX), and all the server can do then is to do any garbage collecting that may be done and close the connection (and maybe wait for the client to reconnect to restore a broken session). Servers don't connect to clients (with exception - FTP service).

rhg

Trainee

  • "rhg" is male

Posts: 178

Location: Velbert, Germany

Occupation: senior software developer

  • Send private message

6

Tuesday, August 17th 2004, 12:19pm

As far as I understand, the original problem is that if you don't gracefully close a connection (example: pull your pc's power plug or unplug the network cable), the remote end won't get any notification unless you have keepalive active. The remote end will simply assume the connection is still alive until it does its next write.

You should implement some kind of long-term inactivity timeout, depending on your applications requirement. For example, in application A it might be valid to assume a connection being idle for more than one hour to be dead. In application B, however, an idle time of one hour might be a common situation so the timeout should be 24 hours or even more.

It also depends on how expensive a connection is on the server side. For example, if you allocate a lot of memory for each connection you might want to clean it up as soon as possible.

I hope this helps you to decide how to proceed.

7

Tuesday, August 17th 2004, 2:19pm

Quoted

UDP isn't a connection protocol - you don't have a "connection" here, so you don't have to (and even don't have the ability to) close it. UDP is datagram based, it just sends some data, but doesn't assure that it reaches destination at all, and even if it does, it doesn't assure that datagrams don't get mixed, cut, reordered...


Yeah...

but this is such a case where one definition of a word means something completely different than another definition.

I understand with connection the actual communication link between two computers for example.
If I want to listen in on a radio or television stream, I connect to that stream, otherwise, I will not hear or see anything.

I don't have to tell that stream "Hey, I'm ..., I would like to listen to you", I just connect.

I don't have to tell that stream I'm gone though, so no need for a close() function, I just disconnect.

With tcp you have to close before disconnecting.

Well, that's my understanding of a connection, it might not be the "standard" interpretation of a connection.

  • "wysota" is male

Posts: 4,276

Location: Warsaw, POLAND

  • Send private message

8

Tuesday, August 17th 2004, 2:38pm

Quoted

Originally posted by tbscope
Yeah...

but this is such a case where one definition of a word means something completely different than another definition.

I understand with connection the actual communication link between two computers for example.
If I want to listen in on a radio or television stream, I connect to that stream, otherwise, I will not hear or see anything.

I don't have to tell that stream "Hey, I'm ..., I would like to listen to you", I just connect.


I'd rather compare UDP to sending a message by smoke-signals or something... You address the message and send it, you don't get any notification from the other end, nor does the other end know for sure that it was sent by you, it doesn't have to signal "Hey, I got you message fine!" or "I'll stop looking at the sky now so don't send me signals anymore, cause I won't see them".

Because of that, there is no way to get a notification that something happened on the other side (other than receiving a message from the host telling that it received the message). Look at this - UDP datagrams can be addressed to more than one host (via broadcast or multicast), so you don't know who is listening to them (if anybody at all). You can't call broadcast transmission a connection (no matter the interpretation), it's rather like a scream :)


As for the original problem, as I said, POSIX sockets notify the server by sending 0 bytes through the socket when the connection is interrupted (it is like "broken pipe" - I'm listening, but noone is talking), it is possible that Qt gives a simmilar behaviour.

But the easiest way to resolve this problem in Qt is to use non-blocking socket operations and set a simple timer. When it fires, either disconnect or test if the network is operational.

rhg

Trainee

  • "rhg" is male

Posts: 178

Location: Velbert, Germany

Occupation: senior software developer

  • Send private message

9

Tuesday, August 17th 2004, 4:29pm

Quoted

Originally posted by wysota
As for the original problem, as I said, POSIX sockets notify the server by sending 0 bytes through the socket when the connection is interrupted (it is like "broken pipe" - I'm listening, but noone is talking), it is possible that Qt gives a simmilar behaviour.


If this was true no auto.dialing VPN router in the world would work. These devices interrupt the line when the connection is idle. As soon as any end tries to send it re-dials into the other end transparently.

Think of it. If you unplug your network cable or switch off your pc - nothing happens to the socket on the remote side. The next write, however, most probably gives you a "connection reset by peer". But besides that you will never get notified unless you have keepalive active.

  • "wysota" is male

Posts: 4,276

Location: Warsaw, POLAND

  • Send private message

10

Tuesday, August 17th 2004, 5:22pm

If the "breaking" host is unable to send any packet, then it can't notify the other end of course (it is so if you have such a VPN or have a power failure) but I think the connection will be reset by the operating system itself (after some timeout) and then the \0 would be written to the app, I'd have to check that (of course it is also OS dependant). On the other hand, if the machine doesn't send anything through the socket (either because of some user action or because of some OS event), it won't notice the breakdown (because it's timeouts won't be fired), so if you have to know the connection state, you should use some kind of keep-alive, but if you don't, you can use "auto keep-alive" when sending data through the socket, it depends on the behaviour of the server, if it can init the dialog with a client, keep-alive is not needed, if it just waits for a client, then you have to either use keep-alive from the client side (or a server request for a keep-alive packet, but then you don't need an answer, so it is not strictly keep-alive) or close the connection from the server side and hope that the client reconnects and will be able to continue the session or begin a new one.

Edit: Oh, by the way... those auto dialing routers could use such \0 character - they know that the other end disconnected and that they have to connect again (nobody says they have to pass this EOF to a higher layer), but it's just a wild guess.

This post has been edited 1 times, last edit by "wysota" (Aug 17th 2004, 5:26pm)


djanubis

Professional

  • "djanubis" is male

Posts: 1,370

Location: Moulins France

Occupation: Software ingeneering

  • Send private message

11

Tuesday, August 17th 2004, 8:43pm

In other words, you describe what RFC say for each and every protocol.
No generic library can hold all and every way to decide when a connection is lost.

Solutions are: time-out, timers, flying saucers... One should read RFCs for wanted (needed) protocol.

edit More on this, when on server side deciding to close a connection, we have to deal with unparsed data already received. This is, by no means, as simple as saying it.

A good discussion occured on MPlayer develpment about how to decide when a connection was broken.
Never patch not working code. Rewrite it !
Never patch badly designed classes. Recreate them cleanly.
(Excerpts from Computing Bible)

Home of the Lab project

This post has been edited 1 times, last edit by "djanubis" (Aug 17th 2004, 8:47pm)