How send a binary file in segments over network in C? - c

I am a bit puzzled over how to send a file from an http server to a client(web-browser).
First I send the header and my next task is to send the file content. However I want to send it in segments of say 512 bytes instead of the whole file at once as I ran into some problems.
I am a bit lost on how to achieve that. Here is what I want
read file1;
while (seg=get_next_segment(file1)){
do
send(seg)
until (seg_is_sent)
}
However I can't seem to find the appropriate functions to achieve that. fread and fseek crossed through my mind but the first one reads the whole file at once and with fseek I don't see a way to just grab a portion from a file(instead of reading from the file pointer until the end of the file).

freaddoes not read a whole file to the end. It reads exactly how much you tell it to read.
size_t
fread(void *restrict ptr, size_t size, size_t nitems,
FILE *restrict stream);
size_t
fwrite(const void *restrict ptr, size_t size, size_t nitems,
FILE *restrict stream);
Both functions take a size and nitems. You could set the size to 512, and the number of items to 1 (or vice versa) and read just that portion of the file.

From the man page:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
The function fread() reads nmemb elements of data, each size bytes long, from the stream pointed to by stream, storing them at the location given by ptr.
As you can see, you don't have to read the whole file with fread, you can read it in nmemb size chunks.
If you are writing your own web-server in C, you may want to have a look at libmicrohttpd, which is a web-server in C for embedding into other applications, it can handle streaming a file for you.

I'm feeling kind... How about something like this:
for (;;)
{
char buffer[512];
size_t nread = fread(buffer, sizeof(char), 512, fp);
if (nread > 0)
send_to_socket(buffer, nread);
if (nread < 512)
{
if (feof(fp))
printf("End of file\n");
if (ferror(fp))
printf("Error reading\n");
break;
}
}

Related

How does fread() know where to look in a .wav file? [duplicate]

Simple question,
When i use fread:
fread(ArrayA, sizeof(Reg), sizeBlock, fp);
My file pointer, fp is moved ahead?
Answer: Yes, the position of the file pointer is updated automatically after the read operation, so that successive fread() functions read successive file records.
Clarification: fread() is a block oriented function. The standard prototype is:
size_t fread(void *ptr,
size_t size,
size_t limit,
FILE *stream);
The function reads from the stream pointed to by stream and places the bytes read into the array pointed to by ptr, It will stop reading when any of the following conditions are true:
It has read limit elements of size size, or
It reaches the end of file, or
A read error occurs.
fread() gives you as much control as fgetc(), and has the advantage of being able to read more than one character in a single I/O operation. In fact, memory permitting, you can read the entire file into an array and do all of your processing in memory. This has significant performance advantages.
fread() is often used to read fixed-length data records directly into structs, but you can use it to read any file. It's my personal choice for reading most disk files.
Yes, calling fread does indeed move the file pointer. The file pointer will be advanced by the number of bytes actually read. In case of an error in fread, the file position after calling fread is unspecified.
Yes, The fp will be advanced by the total amount of bytes read.
In your case the function fread reads sizeBlock objects, each sizeof(Reg) bytes long, from the stream pointed to by fp, storing them at the location given by ArrayA.
Yes, it does. It could be checked by using ftell() function in order to show current position (in fact, bytes read so far), take a look it:
int main() {
typedef struct person {
char *nome; int age;
} person;
// write struct to file 2x or more...
FILE *file = fopen(filename, "rb");
person p;
size_t byteslength = sizeof(struct person);
printf("ftell: %ld\n", ftell(file));
fread(&p, byteslength, 1, file);
printf("name: %s | age: %d\n", p.nome, p.idade);
printf("ftell: %ld\n", ftell(file));
fread(&p, byteslength, 1, file);
printf("name: %s | age: %d\n", p.nome, p.idade);
//...
fclose(file);
return 0;
}

C Fread Split Textfile into Chunks

i've got a Textfile of Unknown Size and have to send it via Sockets from my Server to the Client in Chunks of a certain (variable Size).
How can i use Fread for that Task? I read alot about Fread but im Struggeling with the kind of Pointer i should pass that function in my Case?
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
How can i use fread for that task?
Simply keep sending chunks (of fixed size) from the Server to the Client, until there is nothing else to be sent by the Serve.
What kind of pointer I should pass that function in my case?
Anything.
Check fread()'s example, where the buffer that is passed in fread() is of type char, and fread() simply allows for it, since the first argument of that function is:
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
So just pass the array you are using to store the data (the chunks) to the function.
To read file as chunks and send them to socket you'll have to decide a size of the chunk.
For example: 4096 is perfect size that's not too big or not too small!
Example
We choose 4096 bytes as the chunk size. It's btw customizable.
Send the chunk data to the Client when received from file.
#include <stdio.h>
int main(ssize_t argc, char** argv)
{
// We're going to use "rb" because in (WINDOWS) you need it!
FILE* fp = fopen(argv[1], "rb");
char byte_buffer[4096];
size_t bytes_read = 0;
while(( bytes_read = fread(&byte_buffer, 4096, 1, fp) )> 0)
send_data_chunk_to_client_somehow(/* your parameters here */);
}
The text file should be read in chunks and send them to the Client.
fread(3) ― Binary stream I/O
fread(3) is compatible with both text and binary streams, it's a part of ANSI C. The POSIX read(3) is a equivalent to the function and faster than it.
size_t fread(void* ptr, size_t size, size_t nmemb, FILE* fp);

Difference between write and fwrite not the same results

If I have piece of code that writes out text like this: write(1, buf, bytes); why doesn't the same works for writing to a file fwrite(1, buf, bytes,f1);?
Where f1 is declared as FILE *f1; and f1=fopen("Test.txt", "wb");. The tutorials I'm looking at indicate that it should work. I'm C# coder and not a C coder and would like some help with this.
The signature of fwrite is:
fwrite(const void * ptr, size_t size, size_t count, FILE * stream );
While the signature of write is:
write(int fd, const void *buf, size_t count);
If you match your examples you'll see that parameter don't match.
count of write should be size*count of fwrite (which let you specify the size of every element you are writing). In addition write has a file descriptor hardcoded as 1 and which you replace with a FILE* obtained from fopen, how do you know that 1 is referring to that file?

Does fread move the file pointer?

Simple question,
When i use fread:
fread(ArrayA, sizeof(Reg), sizeBlock, fp);
My file pointer, fp is moved ahead?
Answer: Yes, the position of the file pointer is updated automatically after the read operation, so that successive fread() functions read successive file records.
Clarification: fread() is a block oriented function. The standard prototype is:
size_t fread(void *ptr,
size_t size,
size_t limit,
FILE *stream);
The function reads from the stream pointed to by stream and places the bytes read into the array pointed to by ptr, It will stop reading when any of the following conditions are true:
It has read limit elements of size size, or
It reaches the end of file, or
A read error occurs.
fread() gives you as much control as fgetc(), and has the advantage of being able to read more than one character in a single I/O operation. In fact, memory permitting, you can read the entire file into an array and do all of your processing in memory. This has significant performance advantages.
fread() is often used to read fixed-length data records directly into structs, but you can use it to read any file. It's my personal choice for reading most disk files.
Yes, calling fread does indeed move the file pointer. The file pointer will be advanced by the number of bytes actually read. In case of an error in fread, the file position after calling fread is unspecified.
Yes, The fp will be advanced by the total amount of bytes read.
In your case the function fread reads sizeBlock objects, each sizeof(Reg) bytes long, from the stream pointed to by fp, storing them at the location given by ArrayA.
Yes, it does. It could be checked by using ftell() function in order to show current position (in fact, bytes read so far), take a look it:
int main() {
typedef struct person {
char *nome; int age;
} person;
// write struct to file 2x or more...
FILE *file = fopen(filename, "rb");
person p;
size_t byteslength = sizeof(struct person);
printf("ftell: %ld\n", ftell(file));
fread(&p, byteslength, 1, file);
printf("name: %s | age: %d\n", p.nome, p.idade);
printf("ftell: %ld\n", ftell(file));
fread(&p, byteslength, 1, file);
printf("name: %s | age: %d\n", p.nome, p.idade);
//...
fclose(file);
return 0;
}

reading a text file into an array in c

What would be the most efficient method of reading a text file into a dynamic one-dimensional array? reallocing after every read char seems silly, reallocing after every read line doesn't seem much better. I would like to read the entire file into the array. How would you do it?
I don't understand quite what you want. Do you want to incrementally process the file, reading one line from it, then abandon it and process the next? Or do you want to read the entire file into a buffer? If you want the latter, I think this is appropriate (check for NULL return for malloc and fopen in real code for whether the file exist and whether you got enough memory):
FILE *f = fopen("text.txt", "rb");
fseek(f, 0, SEEK_END);
long pos = ftell(f);
fseek(f, 0, SEEK_SET);
char *bytes = malloc(pos);
fread(bytes, pos, 1, f);
fclose(f);
hexdump(bytes); // do some stuff with it
free(bytes); // free allocated memory
If mmap(2) is available on your system, you can open the file and map it into memory. That way, you have no memory to allocate, you even don't have to read the file, the system will do it. You can use the fseek() trick litb gave to get the size.
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
EDIT: You have to use lseek() to obtain the size of the file, .
int fd = open("filename", O_RDONLY);
int nbytes = lseek(fd, 0, SEEK_END);
void *content = mmap(NULL, nbytes, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
If you want to use ISO C, use this function.
It's litb's answer, wrapped with some error handling...

Resources