Reputation: 164
I am trying to use the http protocol GET to ask the server to send me a picture. It compiles and will ask for the picture but the server only will send me a small part of it.
My code is:
#include <iostream>
#include <string>
#include <Windows.h>
#include <fstream>
#include <stdlib.h>
#include <winsock.h>
#pragma comment(lib, "wsock32.lib")
using namespace std;
#define BUFFERSIZE 1024
void die_with_error(char *errorMessage);
void die_with_wserror(char *errorMessage);
int main(int argc, char *argv[])
{
string request;
string response;
int resp_leng;
char buffer[BUFFERSIZE];
struct sockaddr_in serveraddr;
int sock;
WSADATA wsaData;
char *ipaddress = "210.125.167.240";
int port = 80;
//http://cwc.ghc.ac.kr/skin/base/board/view_brit2.gif
request+="GET /skin/base/board/view_brit2.gif HTTP/1.0\r\n";
request+="Host: cwc.ghc.ac.kr\r\n";
request+="\r\n";
//init winsock
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0)
die_with_wserror("WSAStartup() failed");
//open socket
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
die_with_wserror("socket() failed");
//connect
memset(&serveraddr, 0, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = inet_addr(ipaddress);
serveraddr.sin_port = htons((unsigned short) port);
if (connect(sock, (struct sockaddr *) &serveraddr, sizeof(serveraddr)) < 0)
die_with_wserror("connect() failed");
//send request
if (send(sock, request.c_str(), request.length(), 0) != request.length())
die_with_wserror("send() sent a different number of bytes than expected");
//get response
response = "";
resp_leng= BUFFERSIZE;
while (resp_leng == BUFFERSIZE)
{
resp_leng= recv(sock, (char*)&buffer, BUFFERSIZE, 0);
if (resp_leng>0)
response+= string(buffer).substr(0,resp_leng);
}
ofstream myfile;
myfile.open ("C:\\a\\example.gif");
//display response
cout << response << endl;
//get response
response = "";
resp_leng= BUFFERSIZE;
while (resp_leng == BUFFERSIZE)
{
resp_leng= recv(sock, (char*)&buffer, BUFFERSIZE, 0);
if (resp_leng>0)
response+= string(buffer).substr(0,resp_leng);
}
//display response
cout << response << endl;
myfile << response;
myfile.close();
//disconnect
closesocket(sock);
//cleanup
WSACleanup();
return 0;
}
void die_with_error(char *errorMessage)
{
cerr << errorMessage << endl;
exit(1);
}
void die_with_wserror(char *errorMessage)
{
cerr << errorMessage << ": " << WSAGetLastError() << endl;
exit(1);
}
/*
It compiles and runs fine the output is:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
ETag: W/"60-1144808550000"
Last-Modified: Wed, 12 Apr 2006 02:22:30 GMT
Content-Type: image/gif
Content-Length: 60
Date: Wed, 22 Feb 2012 04:29:04 GMT
Connection: close
GIF89a
*/
What is wrong, why does it not download the full picture?
Upvotes: 1
Views: 2139
Reputation: 1
Also you should clear your recieve buffer out with each cycle. Put this as the first line within the loop.
ZeroMemory(buffer,sizeof(buffer));
You can get a lot of unexpected results with binary data left in the buffer.
Upvotes: 0
Reputation: 993403
It looks like this loop is the problem:
while (resp_leng == BUFFERSIZE)
{
resp_leng= recv(sock, (char*)&buffer, BUFFERSIZE, 0);
if (resp_leng>0)
response+= string(buffer).substr(0,resp_leng);
}
Calling recv()
will give you some number of bytes from the socket, that may be less than what you ask for. So unlike reading from a file, asking for BUFFERSIZE
bytes may return anywhere from 1 to BUFFERSIZE
bytes.
Instead, loop until you get to the end of the socket:
while (true)
{
resp_leng= recv(sock, (char*)&buffer, BUFFERSIZE, 0);
if (resp_leng <= 0) {
break;
}
response+= string(buffer,resp_leng);
}
Notice that I've also changed the call to the string()
constructor on the last line of the loop (yours would work, but would do more effort than is necessary).
Upvotes: 1