5

I am writing a simple FTP server for a school project. Project is almost done, the only problem I do have is sending a file over socket to a client. I can't write to a socket more than 200kb of data, small files are downloaded succesfully. Can anyone tell me what is the correct way of sending large files over Linux sockets ?

Thanks in advance.

PS I am using C and 32-bit linux, server working in PORT mode, been using low level open,write,read and other functions such as sendfile,send,sendto.

piotr
  • 5,657
  • 1
  • 35
  • 60
user1122920
  • 61
  • 1
  • 1
  • 2
  • Can you show us some code? Why can't you write over 200kb ? – user703016 Dec 30 '11 at 12:46
  • Unless the project requires that you use sockets directly, the easy way is to implement your server with libcurl (google it). – Pete Wilson Dec 30 '11 at 12:48
  • What client are you using? Is it when the server receives or sends the file? – Some programmer dude Dec 30 '11 at 12:49
  • Clients - popular FTP clients such as FlashFXP Well, I need to write to sockets directly Sample code which I tried and it hung the forked process http://stackoverflow.com/questions/2014033/send-and-recive-file-in-socket-programming-in-linux-with-c-c-gcc – user1122920 Dec 30 '11 at 13:08
  • Are you sure that you're reading the entire file into memory? This will take more than one read on most machines. Are you checking the return value of the reads and sends? They may tell you themselves what is going on, if you're currently ignoring the return values you should pay attention to them. – Adam Davis Dec 30 '11 at 13:39
  • By the way, are you using `sendfile` for this? Are you providing it with the actual file size? Is the offset set to the beginning of the file? – Some programmer dude Dec 30 '11 at 13:44
  • Using the sendfile function with offset=0 and the file size (which I got from stat() function) also hangs the programme ;x – user1122920 Dec 30 '11 at 14:03

2 Answers2

5

you can mmap the file and write it on the socket from there, you can also get its size using fstat, like this:

fd = open(filename, O_RDONLY);
struct stat s;
fstat(fd, &s); // i get the size
adr = mmap(NULL, s.st_size, PROT_READ, MAP_SHARED, fd, 0); // i get the adress
write(socket, adr, s.st_size); // i send the file from this adress directly

You may want to send just the size of the file before you send it entirely. Your client maybe want to send you that he got the good size and that he can manage to download it.

isabel
  • 106
  • 4
4

One idea might be reading the file chunk by chunk, something like:

Pseudo-code

#define CHUNK_SIZE 1000

void send(){
  uint8_t buff[CHUNK_SIZE];
  int actually_read;
  while((actually_read = read(fd, buff, sizeof(buff)) > 0)
     sendto(sock_fd, buff, actually_read, 0);
}

You should add some error checking, but the idea is to read a considerable amount of bytes from the file you want to send and send that amount. In the server side you need to do a similar thing, by reading from the socket the arriving chunks and writing them to a file. You might want to prefix some metadata to buff just to tell the server which file you're transmitting if you want to handle multiple file transfers. Since FTP uses TCP you shouldn't worry about losing data.

Again, this is just an idea. There are multiple ways of doing this I suppose.

Fred
  • 16,367
  • 6
  • 50
  • 65
  • 1
    Try a chunk size larger then 4096 bytes since this is the default linux read / write page size. So if you would use a buffer larger then 4096 bytes you would avoid the performance lost for the 4 extra syscalls. – DipSwitch Dec 30 '11 at 13:06
  • I'll try that, anyways I'm going to try my server on some other Linux distribution – user1122920 Dec 30 '11 at 13:09