5

I am designing a file syncing application (like DropBox). The client keeps a persistent Secure (SSL) TCP socket with the server on port 443. Whenever a file is created/changed/deleted on the client, a packet containing the relevant data is sent over the socket to the server, which processes it to update the file on the server. Similarly when something changes on the server, it sends the relevant data to the client, which then updates the local copy.

This is working absolutely fine when the server is on the local computer, or on the local LAN. What I am worried about is when the client is on an unreliable network. So my question is what are the best practices, issues to consider while designing such an App?

For example, say when a file is created on the Client, should the client just send the data to the server and forget about it, or should it wait for an acknowledgment from the server within a certain time period, failing which send the data again? And what kind of acknowledgement?

Tarandeep Gill
  • 1,506
  • 18
  • 34

3 Answers3

7

TCP abstracts away many network problems: packets always arrive in-order and are resent if the server does not acknowledge that is has received a packet. An unreliable network will cause traffic to become slower, as packets have to be resent.

If the connection is lost anyway, your read() and write() calls will return error return values, so you have to handle that.

Sjoerd
  • 74,049
  • 16
  • 131
  • 175
  • Oh, thats good. So I do not need to worry about lost packets. But I guess I will still need to send acknowledgments in the application layer as "nos" mentioned in a comment to the answer below. – Tarandeep Gill Feb 01 '12 at 12:25
  • So should my app just keep pushing data to the socket, without bothering about anything. For example, say the client has to send a 10 GB file to the server, and the connections is really slow. Should the app just keep writing data to the output buffer? If the network is slow, wouldn't the buffer overflow? – Tarandeep Gill Feb 01 '12 at 12:27
  • If you use something like [sendfile(2)](http://linux.die.net/man/2/sendfile), it'll return the number of bytes it managed to write. You can then poll the FD for write readiness and try writing some more. – James M Feb 01 '12 at 12:31
  • @Tarandeep If you're using TCP it should automatically manage the speed. – Maiku Mori Feb 01 '12 at 12:31
  • The client is in C++. So I assume when I write data to the socket using something like socket->write(fileData), it will not return until all the data has been sent over the network to the server. Is that correct? – Tarandeep Gill Feb 01 '12 at 12:40
  • 1
    @Tarandeep Gill TCP has flow control, so buffers will not overflow. Your read()/write() calls will block (possibly forever unless you're careful) until the data can be sent, or if your sockets are non-blocking, write() will fail and tell you that the buffers are full at the moment. – nos Feb 01 '12 at 14:33
1

The client keeps a persistent Secure (SSL) TCP socket with the server

[..]

should the client just send the data to the server and forget about it, or should it wait for an acknowledgment from the server within a certain time period, failing which send the data again?

If you were using UDP, you'd have to do that. But since you're using TCP, that's all done for you already.

http://en.wikipedia.org/wiki/Transmission_Control_Protocol

You should be aware that TCP is a stream orientated protocol, so your data might not arrive the same way you sent it (i.e. it might arrive one byte at a time, or all at once).

Community
  • 1
  • 1
James M
  • 18,506
  • 3
  • 48
  • 56
  • 2
    Not really. You don't know if everything is ok at the application layer at the other end just because TCP doesn't error out. e.g. the server side could go out of disk space, it could crash just as the client sent the last byte but before that reached the server app, and a number of other application specific stuff that you might needto care about. – nos Feb 01 '12 at 12:17
  • That's beyond the scope of "socket programming", no? – James M Feb 01 '12 at 12:18
  • Thanks for the comments guys, any response to my comment on Sjoerd's answer above? – Tarandeep Gill Feb 01 '12 at 12:28
1

You should use acknowledgment even when the server is localhost. Imagine some kind of connection problem occurs when sending information. You need some way to know the result of the operation (using an acknowledgment system, for instance).

I would use something more complex than a simple ACK/NACK reply. For instance, if you change some files in the client, after sending information from the client to the server, the server should reply the number (or a list with the name) of files affected by the update operation. This way, the client can verify everything went OK, or act in consequence.

Josepanaero
  • 136
  • 5