I was having problem in storing .png images , fetched from HTTP server using a C code . I must mention that the images are successfully fetched from server as i analysed wireshark while running the code and content length in header matches buffer size. When i write the buffer data to a .png file using fwrite like this:
Your logic of writing upto *pt != '\0' is not correct in this loop
while((c=*pt)!='\0')
{
fwrite(&c, sizeof(c),1, fp);
pt++;;
}
There can be '\0' character anywhere in the binary data of .png file. So you will not write data after that, hence you are seeing your file size smaller than file size on server.
You should parse the HTTP headers and get value for Content-Length, which gives size of data in bytes and read those many from server and write in local file.
Look for HTTP RFC for more details about the protocol.
There are other problems in your code like
char *pt=malloc(100000);
pt=strstr(rep,"\r\n\r\n");
With this malloc() to pt is not required and leaks the memory.
Try to open the file for output in binary mode , give FILE *fp the flag wb.
Also, why do you try to write byte by byte ? try fwrite(pt,10000,1,fp)
Related
I am struggling with decompression of a Zlib compressed Mime body of AS2 request coming from BizTalk Server.
The thing is:
The HTTP Body I receive looks as expected. I can read the ASCII encoded Mime Header:
"Content-type: application/pkcs7-mime; smime-type=compressed-data; name=smime.p7m\r\nContent-Transfer-Encoding: binary\r\n\r\n"
Ending with two line breaks, I am expecting the compressed body after.
But when I use Ionic.Zlib ZlibStream.UncompressBuffer() to decompress the following bytes it throws an error.
Zlib Header can be identified for example by hex coded bytes "78da". When I start decompressing it from there on, it works fine.
What are the bytes between the two line breaks ending mime header and "78da" starting zlib compressed data?
"3080060b2a864886f70d0109100109a0803080020100300f060b2a864886f70d01091003080500308006092a864886f70d010701a080248004820769"
Next problem, if I read all bytes to the end, the last bytes can not be decompressed.
AS far as I Understood the zLib data should end with adler32 checksum, but how can I identify the end or length of the compressed data without trying to decompress.
I see some trailing bytes after the sucessfully decompressed data:
"1f9b1f1fcbc51f0482000445a59371"
What is that?
Thanks for your ideas!
You cannot find the end of the compressed data without decompressing. You don't need to save the result of the decompression, but you at least need to decode all of the compressed data in order to find where it self terminates.
I'm working on an assignment for class that involves sending .gz binary data from a server to a client using a socket. On the client end, it receives the stream and stores it into an unsigned char buffer. How can I write this compressed data into a new .gz file on the client side?
I can't use gzfwrite() because it was added in 2017 and the old ass machines they're using here to grade my program don't have zlib that recently updated. Any attempt to use it yields "undefined reference".
I've tried using fopen():
FILE *gz = fopen("test.gz", "wb"); // create new .gz on client end
fwrite(buffer, 1, buflen, gz); // buffer contains binary data sent from server
fclose(gz);
but calling gunzip on the resulting .gz fails since file test.gz outputs test.gz: data; as in it's not recognized as a .gz file.
I don't think gzprintf() will work either since it expects a null terminated string, and I have binary data. Ideally I'd like to just sent .gz from the server and write that info to a new .gz file on the client. Any suggestions?
Use gzwrite(gz, buffer, buflen) instead. That function has been there since time immemorial.
I've written a simple http server in C and am now trying to implement HTML files.
For this I need send a response, containing the content of the HTML file.
How do I do that best?
Do I read the file line by line, and if so how do I store them in a single string?
Thanks already!
Here is an example of reading a text file by chunks which, if the file is big, would be faster than reading the file line by line.
As #tadman said in his comment, text files aren't generally big so reading them in chunks doesn't make any real difference in speed but web servers serve other files too - like perhaps photos or movies (which are big). So if you are only going to read text files then reading line by line might be simpler (you could use fgets instead of fread) but if you are going to read other kinds of files then reading all of them in chunks means you can do it the same way for all of them.
However, as #chux said in his comment, there is another difference between reading text files and binary files. The difference is that text files are opened in text mode: fopen(filename,"r"); and binary files must be opened in binary mode: fopen(filename,"rb"); A web server could probably open all files in binary mode because web browsers ignore whitespace anyway but other kinds of programs need to know what the line endings will be so it can make a difference.
https://onlinegdb.com/HkM---r2X
#include <stdio.h>
int main()
{
// we will make the buffer 200 bytes in size
// this is big enough for the whole file
// in reality you would probably stat the file
// to find it's size and then malloc the memory
// or you could read the file twice:
// - first time counting the bytes
// - second time reading the bytes
char buffer[200]="", *current=buffer;
// we will read 20 bytes at a time to show that the loop works
// in reality you would pick something approaching the page size
// perhaps 4096? Benchmarking might help choose a good size
int bytes, chunk=20, size=sizeof(buffer)/sizeof(char);
// open the text file in text mode
// if it was a binary file you would need "rb" instead of "r"
FILE *file=fopen("test.html","r");
if(file)
{
// loop through reading the bytes
do {
bytes=fread(current,sizeof(char),chunk,file);
current+=bytes;
} while (bytes==chunk);
// close the file
fclose(file);
// terminate the buffer so that string function will work
*current='\0';
// print the buffer
printf("%s",buffer);
}
return 0;
}
i have made one client server application in which client sends file (i.e ODT,PDF,MP3,MP4, etc) and server receives file.
i am dividing file in chunks and then transmits them in while loop.
below i have given main logic for both client and server.
when i do loop-back with 127.0.0.1, this code works successfully.
but when i runs client and server on two different PC, after transmitting a file client exits but server keeps receiving and then i have to press ctrl^C. the size of file at server side reaches over 1GB even if file size at client side is only around 4.2 MB.
and in loopback i am not getting such problem.
please tell me the needed corrections.
client.c
#define SIZE 512 // or anything else
char sendbuff[SIZE];
FILE *fr;
fr = fopen("1.mp3","r");
while(!feof(fr)){
count = fread(sendbuff, SIZE,1,fr);
count = send(clientsd, sendbuff,SIZE,0); //clientsd is socket descriptor.
}
send(clientsd, "xyz", 3, 0); //sending '1'. tells server, transmission is over now.
close(fr);
server.c
#define SIZE 512 // same as client side
char recvbuff[SIZE];
FILE *fw;
fw = fopen("2.mp3","w");
while(1){
count = recv(connsd, recvbuff, SIZE,0);
if(!strcmp(recvbuff,"xyz"))
break;
fwrite(recvbuff,SIZE, 1, fw);
memset(recvbuff,0,SIZE);
}
printf("Exit while\n");
fclose(fw);
any other simple and efficient way to do this ?
NOTE : I have changed my question. here some answers are on my old question where i have transmitted "1" instead of "xyz". which was an error.
The most obvious problem is your stop condition on the server side.
You assume that if the first byte received is '1' (0x31) than the transfer is over, but it might be a byte of the data (if the first byte of the chunk in the file is actually '1'). So you need some other way to signal the end of the file. One possibility is to use a wrapping for each packet sent, for example, before each packet send a specific value (for example '1') followed by the length, and when the transfer is complete send '0' to signal that the transfer is completed.
The other problems I can see are that:
You open the files as read text ("r") and write text ("w") which will stop processing if the EOF sequence appears in the middle of the file, instead you need to open them as read/write binary ("rb" / "wb" respectively).
You use chunks of 512 bytes, what if the file is not a multiple of 512 bytes?
I'm working on a simple server that have to work with a browser. When I give it some command, it has to reply me with some html code so to reply my answer. For example I can see the list of the files of a folder etc. I can access my server using localhost:port/somecommand
Now I'm working on donwloading a file from the local hard-disk. What I want to do is enter an url like localhost:port/download/filepath and make the browser download it. When I create the reply I put all things html need to understand that there is a file to download, and infact I have the classical pop-up window that ask me to download the file, but what I receive is bigger than the original file located to the hard-disk, and infact the file is corrupted.
Here the code:
This is the html I send back
HTTP/1.0 200 OK
Date: Tue Apr 10 16:23:55 2012
Content-Type: application/octet-stream
Content-Disposition: attachment; filename=mypic.jpg
Content-Length: 2574359
//empty line here
(I followed The Content-Disposition Header Field text )
then I read from file and I send back html first and what I read from file then:
int file=open(name,O_RDONLY);
void * data=malloc(buf.st_size+1); //buf.st_size is the correct file size
size_t readed=read(file,data,buf.st_size);
send(sd_current, html, DIRSIZE, 0); //html is a string containing what you I showed you
send(sd_current, data, readed);
This result the file I can download using localhost:port/download/filepath to be bigger than original then corrupted, but I can't get rid of why. Can someone help me?
Things to check:
is DIRSIZE really the size of the http header? (Since the size should vary, and capitals normally means constant).
Is the read successful?
How is the file corrupted?
Are the line endings on the http header correct? They should be \r\n
EDIT:
If DIRSIZE is not the size of the header, then the rest of the buffer (containing NULLs or junk) will be sent to the other size.
So the other side sees the HTTP header, then starts receiving data - starting with the rest of the html buffer, then the contents of the file.
Then depending on the receiver, it either stops at the Content-Length header size, or carries on while the stream is still delivering data.
Does that match your result contents: Some junk at the beginning, followed by the expected file contents?
Content-Length: 2574359, 2574359 should be the size of your jpg file, but I see nothing in your code to put that in the html portion. buf.st_size == 2574359 ?