LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Sending files over udp sockets in C (https://www.linuxquestions.org/questions/programming-9/sending-files-over-udp-sockets-in-c-254978/)

raszagal 11-15-2004 04:17 AM

Sending files over udp sockets in C
 
Hi
im trying to send files over a socket datagram in C between 2 clients.
Can anyone tell me whats the best way to "read" the file i want to send, and split it if necessary, and then send send it?
thks

rjlee 11-15-2004 05:27 AM

You can use the read() method to read a file in chunks of (up to a) fixed size. Call it repeatedly, and send each packet, until you hit the end of the file. See the read manpage.

Assuming that you want to do this reliably, you'll also need some sort of CRC checksum in each packet to identify if it is corrupted in transit or not ,and a sequence number (because packets can become shuffled over longer routes). Alternativly, use TCP which handles this detail itself.

On the other side, you will need to read the file in in blocks, sort them into sequence (note that they are likely to be more-or-less in sequence), check the checksums, acknowledge the valid packets (use CRC checksums again), and then out the headers.

You should also resend packets after a timeout (see seek() and tell()) if its acknowledgement doesn't arrive, or is corrupted.

To generate a CRC checksum, I don't know of a method off-hand, but you might try searching for something suitable on sourceforge.net

raszagal 11-15-2004 01:11 PM

thks
i have one more question... when i use the read() function, from what ive seen, i read it to a buffer of type char ? does it work files other
that text only files? like jpeg's etc... or do i have to read to somekind of byte stream...?
thks again :P

itsme86 11-15-2004 01:41 PM

You can read() any type of data. It's just that an unsigned char array serves as a very nice buffer for any data type.

For instance, you could have do something like this:
Code:

int num;

read(fd, &num, sizeof(int));


shy 11-16-2004 03:10 AM

Sending files through UDP seems to be a very strange idea. I'm almost sure you want to send the files reliably, so to do this (as rjlee pointed you) you should use some sort of CRC, sort parts of files, request resending of lost datagrams (btw, UDP datagrams can be lost even if UDP is used to communicate between 2 programs running on the same host), and so on, e.g. you have to implement TCP.

Why bother implementing it, if it's already done?

raszagal 11-16-2004 05:37 AM

i have to do it by udp... its a school project and its demanded its over a udp "connection" :(
thks for the help

shy 11-16-2004 05:41 AM

Try to find IMHO the best book on socket API "UNIX network programming" by Richard Stevens. Reading it will defenitely help you in writing your program.

rjlee 11-16-2004 11:28 AM

Quote:

Originally posted by raszagal
thks
i have one more question... when i use the read() function, from what ive seen, i read it to a buffer of type char ? does it work files other
that text only files? like jpeg's etc... or do i have to read to somekind of byte stream...?
thks again :P

To read non-text files, you generally specify unsigned char, but char will work just as well so long as you don't do any bitwise operations on it (<< >> & | or ^). read() itself doesn't care what type of buffer you pass it; it can even be a struct or a union so long as it's big enough to hold all the data.

raszagal 11-21-2004 01:49 PM

hi again...
im having some trouble when reading the file i want to send. Im trying do build a message containing
in the first position the char 'F' ( for file) followed by file id ( an int ) a pkt_id ( an int ) and finally a block of data frm the file
im trying to send
i have this code just to try out adding info to the message im sending but it isnt writing anything to a new file.
if you could take a look... that would be great thks

-----------------------------------------------------------------------------------------------
#define FAIL 0
#define SUCCESS 1
#define BLOCKSIZE 512

int fileid = 5;
int pkt = 9;

unsigned char* write_block(unsigned char* data){
unsigned char *mensagem = (char *)calloc(1, 10 + BLOCKSIZE);
FILE *fp;
int pkt_number = 1;
int idfile = 1;
char *N="\n";
char *F="F";
mensagem[0] = 'F';
*( (int *) (mensagem + 1)) = fileid;
*( (int *) (mensagem + 5)) = pkt;
pkt++;
*( (unsigned char *) (mensagem + 9)) = data;
printf(" mensagem enviada : %s\n", mensagem);

idfile = *((int *) (mensagem + 1));
pkt_number = *((int *) (mensagem + 5));

printf("id do file : %d\n", idfile);
printf("id do pacote : %d\n", pkt_number);

return mensagem;
}

int file_size(char *infile){
FILE* fp;
unsigned char bloco[BLOCKSIZE];
unsigned char temp;
int num_read;
int size = 0;

if ((fp = fopen( infile, "rb")) == NULL){
printf("Error opening file %s for input.\n", infile);
return FAIL;
}
if ((fp = fopen("teste.o", "wb")) == NULL){
printf("Error opening file for input.\n");
return FAIL;
}
while ((num_read = fread(bloco, sizeof(char), BLOCKSIZE, fp)) > 0){
size += num_read;
temp = write_block(bloco);
fwrite( temp + 9, sizeof(char), num_read, fp);
}
printf("bytes : %d\n", size);
fclose(fp);
if (ferror(fp)){
printf("Error reading file %s\n", infile);
return FAIL;
}
return SUCCESS;
}

int main(){
file_size("fila.o");
return 0;
}

-------------------------------------------------------------------------------------------

rjlee 11-27-2004 12:49 PM

Quote:

Originally posted by raszagal
Code:

        if ((fp = fopen( infile, "rb")) == NULL){
                printf("Error opening file %s for input.\n", infile);
                return FAIL;
        }
        if ((fp = fopen("teste.o", "wb")) == NULL){
                printf("Error opening file for input.\n");
                return FAIL;
        }


Assuming that both files open correctly, The fp pointer will now point to a structure representing the output file, teste.o. when you subsequently try to read from fp, you will be reading from the teste.o file, which will fail because the file is write-only.

You would have trapped this error if you had used errno.
Code:

#include <errno.h>
at the start of the file, then do
Code:

errno=0;
immediately before any standard I/O functions, like read or write. Then you test if errno==0 after the I/O; if not, an error has occurred and the value of errno (or the string message strerror() from string.h) will tell you what the error was.

You shouldn't assume that any I/O will be successful, because that isn't under the program's control; this applies to networked I/O as well as file or device I/O.

The result ferror() can also be used in place of errno (and is cleaner but potentially slower than errno), but you must still use it after each and every I/O call; if you do an I/O that fails followed by one that suceeds, without resetting the error state in between, then the error condition it returns could be anything.


All times are GMT -5. The time now is 12:44 AM.