Reputation: 53
I would like to know how to download an .exe file using sockets in c++/c. I'm using cygwin and g++
I've tried with berkeleys sockets but i can't seem to download the file. I've embedded my code below:
#include <fstream>
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <string>
#include <sstream>
#include <iostream>
#include <map>
using namespace std;
int main(){
int sock_descriptor; // integer number to access socket
struct sockaddr_in serv_addr; // uses predefined sockaddr_in struct
struct hostent *server; // from netdb.h to determine host name out of ip address
char recvBuff[1024]; // Receiving buffer
char hostname[] = "localhost";
char req[] = "GET /fjernsupport.exe HTTP/1.1"
"Host: localhost\n"
"Connection: keep-alive\n"
"Cache-Control: no-cache\n"
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\n"
"Pragma: no-cache\n"
"User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31\n"
"Accept-Encoding: gzip,deflate,sdch\n"
"Accept-Language: en-GB,en;q=0.8,en-US;q=0.6,da;q=0.4\n"
"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3\n\n";
sock_descriptor = socket(AF_INET, SOCK_STREAM, 0); // SOCK_STREAM = TCP, AF_INET = DOMAIN
if(sock_descriptor < 0){
std::cout << "Failed creating socket\n" << std::endl;
}
bzero((char *)&serv_addr, sizeof(serv_addr));
server = gethostbyname(hostname);
if(server==NULL){
std::cout << "Failed to find server name" << std::endl;
return 0;
}
serv_addr.sin_family = AF_INET;
memcpy((char *) &(serv_addr.sin_addr.s_addr), (char *)(server->h_addr), server->h_length);
serv_addr.sin_port = htons(80); // Ensures integer interpretion is correct
if(connect(sock_descriptor, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){
std::cout << "Failed to connect to server" << std::endl;
}else{
std::cout << "Succesfully connected" << std::endl;
}
cout << "SEND: " << req << endl;
write(sock_descriptor, req, sizeof(req));
bool isFile = false;
ofstream outFile;
outFile.open("outfile.exe", ios::out | ios::binary);
while(true){
memset(recvBuff, 0, 1024);
if(read(sock_descriptor, recvBuff, sizeof(recvBuff)-1) > 0){
//cout << "RECV: " << recvBuff << endl;
outFile << recvBuff;
//cout << "WRITING THIS: " << recvBuff << endl;
//cout << "Newline? " << endl;
}else{
outFile.close();
cout << "Returning here";
return 0;
}
}
outFile.close();
cout << "finished";
return 0;
My code is connecting perfectly and getting the correct response headers, exept the data thing. It isen't moving the data to the file. The main concern is that i'm not sure whether it is the wrong data i'm recieving or if it's an incorrect way of creating the outfile.exe.
I know that the code above is also writing the response http header files to the file. But even that doesen't make the file big enough. The outfile.exe is only about 763kbs while the fjernsupport.exe is about 3mb
Upvotes: 4
Views: 2033
Reputation: 70372
You are trying to save binary data as if it is a NUL terminated string here:
outFile << recvBuff;
Instead, you should save the return value of the read()
call (as it indicates how many bytes were saved to the buffer), and then write that many bytes to the outFile
.
if((bytes = read(sock_descriptor, recvBuff, sizeof(recvBuff))) > 0){
//...
outFile.write(recvBuff, bytes);
Upvotes: 2