user1015551
user1015551

Reputation: 197

Async Sockets, Receive multiple files on same connection

I have a server that is going to transfer multiple files to a client over a single connection. The packet from server is in the following format: unique_packet_id | file_content

I have onDataReceived function which I need to work like this:

    public class TRACK_ID {
         public string id;
         public string unknown_identifier;
    }

    List<TRACK_ID> TRACKER = new List<TRACK_ID>();

    public void OnDataReceived(IAsyncResult asyn)
    {
        try
        {
            log("OnDataReceived");
            SocketPacket theSockId = (SocketPacket)asyn.AsyncState;

            int iRx = theSockId.thisSocket.EndReceive(asyn); 

            // .. read the data into data_chunk

                // if seperator found, that means we got an first chunk with the id
                if (data_chunk.Contains("|") == true)
                {
                    // extract unique_packet_id from the data
                    // bind unique_packet_id to an some kind of identifier? how!!??
                    TRACK_ID new_track = new TRACK_ID();
                    new_track.id = unique_packet_id;
                    new_track.unknown_identifier = X;

                    TRACKER.add(new_track);

                } else {
                   // no seperator found - we're getting the rest of the data
                   // determinate the unique_packet_id of the incoming data so we can distinguish data/files           
                   string current_packet_id = "";

                   for(int i=0; i<TRACKER.count; i++){
                       if(TRACKER[i].unknown_identifier == X){
                               current_packet_id = TRACKER[i].id; // we found our packet id!
                               break;
                       }
                   }

                   // now we got our packet_id and know where to store the buffer

                }


             WaitForData..
        }

     }

I need a variable X that will allow me to track where to store each incoming buffer

If I closed connection for each file, I could bind unique_packet_id to socket_id (socket_id would be X), but since I'm using the same connection, socket_id always stays the same so I have to use something else for this X variable.

Only other solution I can think of is sending the unique_packet_id in each chunk of data. But that seems like not the best way to do it. Then I would have to split the file buffer into chunks and append the id to each chunk. Any other ways how to accomplish this? Thanks!

Upvotes: 1

Views: 755

Answers (1)

Celada
Celada

Reputation: 22261

You didn't say if you're using a stream socket or a datagram socket.

If you're using a datagram socket (e.g. you're using UDP/IP) then you will always receive a whole packet all at once, so you can identify the data because it goes with the unique_packet_id that was found before the | at the beginning of the current packet.

If you're using a stream socket (e.g. you're using TCP/IP) then I think you have a problem. Your packet format isn't delimited or escaped, so how will you know where one packet ends and the next one begins?

If you are using a stream socket, you need to use, for example, a packet format like this:

  • unique packet ID (say, in ASCII, terminated with CRNL —­ or whatever you choose)
  • content length (same format)
  • packet payload

The receiver can find the end of the packet because it knows how many bytes will be part of the payload.

You will also need to be prepared for the case where you get one of your packets in small pieces. For example, your callback function might be called once with part of the unique packet ID, called again with the rest of the header and part of the payload, and again with the rest of the payload and the complete following packet tacked on to the end. Or you may get three whole packets and part of a fourth in a single call to your callback function.

The other possible solution you mention, that of sending the unique_packet_id in each chunk of data, is not possible, because the sender doesn't know how the data will be chunked up when it is delivered to the receiver.

Upvotes: 1

Related Questions