0

I have an asychronous file transfer using boost::asio.
Multiple files can be transfered at the 'same time'. Same time as in - file packet for file 1, next packet for file 3, next for file 2, ... No threaded file-transfer in the same socket.

Currently I'm sending each time a 10KB packet/message/string, including a small header with OPCode, a GUID, etc, from sender to receiver. When the receiver has received the packet it will send a small acknowledge packet (~20byte +- 4) back to the sender. When the sender has received the packet, it will send the next packet for the corresponding file to the receiver and it starts again.

My question is, if this looks like a reasonable approach, or if there's a better one.
Side note: I'll also use a zip library later in order to send more/less data per packet.
Before using this "style" I just kept 'spamming' all packets from sender-side to receiver-side w/o any acknowledgement. The "packets"/messages are being split, and therefore the application does not recognize the incoming data (no header) as valid and discards it. This basically means the data is lost at the receivers side.

What would you recommend, what is the best approach to send data fast over a TCP (opt. SSL too) connection, assuming both ends have different upload/download rates ?

If you need more information about something specific, please leave a comment.


Edit:

As I send multiple files, my "packets"/messages include, as mentioned above a GUID in the header. Multiple files can be transfered at one time. Sending large data, such as 5MB often splits the message, and this means that at messages w/o the header arrive, and therefore break the system.

One easy solution would be to re-structure my code a little bit and send file by file. This would work if the header is sent once, and right after it the data-/filechunk is sent without header in larger packets. As bЈовић said, TCP will take care of the rest.

In my current "solution"/approach I sadly need the mentioned "system" I've explained. For other transfers except this one, I'm sending file by file and the data is split.

6
  • You've needlessly limited your throughput to 10KB per file per round trip time. If you're only sending one file and you're sending it around the world, you'll limit to about 400Kbps for pretty much no reason. Also, you use the word "packet" to mean an application protocol data unit. You should really avoid doing this as creates all kinds of confusion. Perhas you want "message"? Aug 19, 2016 at 10:51
  • @DavidSchwartz I've updated the question. Aug 19, 2016 at 11:54
  • 1
    In a working TCP implementation data will never be lost in the way you describe. You can have your sending program transmit a megabyte in an instant, and your receiving program read a byte per second, and everything will still work and no data will be lost. You must examine what the problem was that led to your losing data in what you describe as your "spamming" architecture, because whatever it is, it is a bug, and could spontaneously lead to data loss in other circumstances. Aug 19, 2016 at 11:54
  • @MartinKochanski I expressed it too unclear. No data is being lost. The "packets"/messages are being split, and therefore the application does not recognize the incoming data (no header) as valid and discards it. Aug 19, 2016 at 11:57
  • @Blacktempel That's just a bug in your code that you need to fix. Aug 19, 2016 at 16:08

2 Answers 2

1

The question is still a little vague, but it looks as if TCP is doing its job, and delivering bytes in the exact sequence in which they were sent.

I wonder if you have been sending bytes into the channel from more than one thread. In that case it is perfectly possible for the following to happen:

  1. Thread A tries to send N bytes through the socket. (N>1).
  2. The buffers being full, the socket accepts M bytes. Thread A therefore will have to re-attempt the transmission of N-M bytes.
  3. Before it re-attempts transmission, Thread A loses the CPU.
  4. Thread B gains the CPU.
  5. In the meantime, some data have been successfully transmitted, so the socket has space available in its buffers.
  6. It would now be possible for Thread A to send the remaining N-M bytes. But Thread A does not have the CPU, so it sends nothing.
  7. Thread B tries to send some bytes of its own. Let's say it sends X bytes.
  8. The buffers having space available, the socket accepts those bytes.
  9. Thread B loses the CPU.
  10. Thread A gains the CPU.
  11. In the meantime, some data have been successfully transmitted, so the socket has space available in its buffers.
  12. Thread A is now able to send the remaining N-M bytes. And it does so.

On the receiving end, the bytes that arrive will be M bytes from thread A; X bytes from thread B; and N-M bytes from thread A. I think that this is what you mean by "split packets".

The only way of being certain of avoiding split packets is if your packet size is 1 byte. No other "packet size" (such as you have tried) will eliminate the possibility of splits: it only reduces the chances.

You need to make sure that each TCP channel has only one thread feeding it. The way I do this is for all the transmitting threads not to send data directly to the socket. They all add their packets to a queue, and one single transmitter thread takes a packet from the queue, transmits it, takes the next packet from the queue, transmits it, and so on. There are then no splits.

No pattern of acknowledgement is needed from the other end, because that is not the cause of your problem.

0

It all depends on the protocol that you established. You did not provide lots of details, but I assume that the sender doesn't really need those return packets, and that it just require one big blob of data.

If my assumptions are correct, then you just need to send whole blob of data at once. The TCP protocol is going to take care of rest. If it fails for any reason, the boost implementation will tell you what happened.

1
  • Updated the question. Aug 19, 2016 at 11:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.