Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to send video over TCP Socket in C

Tags:

c

tcp

sockets

video

I am trying to think of the best way to have a video file sent over a TCP socket. I have made a standard socket program, but after the read command I'm not sure how I can go about saving it.

Code sample

//bind server socketfd
if (bind(sfdServer, (struct sockaddr*)&adrServer, ServerAddrLen) < 0)
    error("ERROR binding");
listen(sfdServer, 5);
while(1){
    printf("Waiting for connections...\n");
    sfdClient = accept(sfdServer, (struct sockaddr*)&adrClient, &ClientAddrLen);
    if(sfdClient < 0)
        error("ERROR accepting");

    printf("Connection Established.\n");
    //set buffer to zero        
    bzero(buff, 2048);
    printf("Reading from client.\n");
    numChar = read(sfdClient, buff, 2048);

    //What should go here?

    close(sfdClient);
    close(sfdServer);

}

Would I just save the buffer as a file movie.mp4 or something like that? I realize I may need to change my buffer size or possibly send it in chunks. But I can't find any good info on the best way to do this. Any help or a point in the right direction would be appreciated!

like image 670
Bryan G. Avatar asked Jan 31 '11 02:01

Bryan G.


2 Answers

You'd write the buffer chunks to a file.

First, open an output file for writing:

   #include <sys/types.h>
   #include <sys/stat.h>
   #include <fcntl.h>


   int outfd;
   outfd = open("movie.mp4", O_WRONLY|);

Then, after the read(), write your bytes:

   numWrite = write(outfd, buff, numChar);

Note that you will need to deal with a number of chunking/buffering cases, such as:

  • Either the read() or the write() returning zero or -1 (error)
  • Reading until no more bytes are available. Right now, your code only reads 2048 bytes and then closes the socket.
  • The write() writing fewer bytes than requested (this can happen on network filesystems)
like image 151
payne Avatar answered Sep 25 '22 13:09

payne


Firstly, you should consider using sendfile() or the equivalent for your system. That is, rather than read a chunk of the file into your memory only to write it back out somewhere, you should memory-map your file descriptor and send everything in one go.

As for chunking, TCP takes care of splitting the stream into packets for you. Ideally the remote node should know exactly how much to expect upfront so it can handle pre-mature termination (that's why HTTP headers contain a content length).

So use some sort of handshake before sending the data. Then the sender should just call sendfile() in a loop, paying attention to the amount of sent data and the returned offet. The receiver should call recv() in a loop to make sure it all arrives (there is no standard "recvfile()").

like image 41
chrisaycock Avatar answered Sep 21 '22 13:09

chrisaycock