Read site body from get request - c++

I try to read site body from get request but I only get the status code and some of start from html text (This is what I got -"HTTP/1.1 200 OK Server: Apa!DOCTYPE html html lang=e"). I would appreciate if you could help me fix the problem. Thanks
Code -
#include <winsock2.h>
#include <WS2tcpip.h>
#include <windows.h>
#include <iostream>
#include <vector>
#include <ostream>
int main(){
// Initialize Dependencies to the Windows Socket.
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
cout << "WSAStartup failed.\n";
system("pause");
}
struct addrinfo hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_socktype = SOCK_STREAM;
/* connect and download the article */
static const char wiki_host[] = "en.wikipedia.org";
struct addrinfo* targetAdressInfo = NULL;
DWORD getAddrRes = getaddrinfo(wiki_host, NULL, &hints, &targetAdressInfo);
if (getAddrRes != 0 || targetAdressInfo == NULL)
{
cout << "Could not resolve the Host Name" << endl;
system("pause");
WSACleanup();
return -1;
}
SOCKADDR_IN sockAddr;
sockAddr.sin_addr = ((struct sockaddr_in*) targetAdressInfo->ai_addr)->sin_addr;
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons(80);
freeaddrinfo(targetAdressInfo);
SOCKET webSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (webSocket == INVALID_SOCKET)
{
cout << "Creation of the Socket Failed" << endl;
system("pause");
WSACleanup();
return -1;
}
if (connect(webSocket, (SOCKADDR*)&sockAddr, sizeof(sockAddr)) != 0)
{
cout << "Could not connect";
system("pause");
closesocket(webSocket);
WSACleanup();
return -1;
}
string http_query = "GET / https://en.wikipedia.org/w/api.php?titles=StackOverflow&action=query&prop=extracts&format=json\r\nConnection: close\r\n\r\n";
if (send(webSocket, http_query.c_str(), http_query.length(), 0) == -1) {
cout << "Could not send the request to the Server" << endl;
system("pause");
closesocket(webSocket);
WSACleanup();
return -1;
}
/* prepare to fetch the wiki article */
string response = "";
while (true) {
static char recv_buffer[4096];
const int bytes_read = recv(webSocket, recv_buffer, sizeof(recv_buffer) - 1, 0);
if (!bytes_read) {
break;
}
if (bytes_read == -1) {
closesocket(webSocket);
WSACleanup();
}
recv_buffer[bytes_read] = '\0';
response += recv_buffer;
};
/* finished with the socket */
closesocket(webSocket);
WSACleanup();
/* parse the http response headers */
size_t cursor = 0;
string response_content;
vector<std::string> response_headers;
const size_t headers_end = response.find("\r\n\r\n");
while (true) {
const size_t line_end = response.find("\r\n", cursor);
if (line_end == std::string::npos) { /* probably due to http error */
break;
}
response_headers.push_back(response.substr(cursor, line_end - cursor));
if (line_end == headers_end) { /* found content */
response_content = response.substr(headers_end + 4); /* skip \r\n\r\n */
break;
}
cursor = line_end + 2; /* skip \r\n */
}
// print the respone
for (int i = 0; i < sizeof(response); i++){
cout << response[i];
}
//print response_content
for (int i = 0; i < sizeof(response); i++){
cout << response_content[i];
}
system("pause");
return 0;
}

This doesn't work:
for (int i = 0; i < sizeof(response); i++){
cout << response[i];
}
Because sizeof(response) is the size of the string object, not the length of the string. You should simply do
cout << response;
If you really want to iterate through the string (which is slower and not recommended) you'd have to use response.size() instead of sizeof(response).
There are a few other issue with your code as well, but this should solve the problem at hand.

Related

Winsock manually send HTTP request gives 403 Forbidden

I am currently trying to understand how HTTP requests work so I am using winsock2 for c++ to try and send some HTTP requests manually.
My code looks like this:
#include <iostream>
#include <SFML/Graphics.hpp>
#include "EasyWinSock.h"
char ip[] = "prnt.sc";
char port[] = "80";
int main() {
easy_win_sock ews(ip, port);
ews.init_win_sock();
ews.create_win_sock();
ews.connect_win_sock();
char sendbuf2[] = "GET /t/gh17d-1645175682/post HTTP/1.1\r\nUser-Agent: kekwtestkekw\r\nHost: ptsv2.com\r\n\r\n";
char sendbuf[] = "GET /111111 HTTP/1.1\r\nHost: www.prnt.sc\r\n\r\n";
ews.send_win_sock(sendbuf, (int)strlen(sendbuf));
DATA *result = ews.recieve_win_sock_text(512); // dynamically allocated
/*
for (int i = 0; i < result->content->size(); i++) {
std::cout << (*result->content)[i];
}
*/
ews.cleanup_win_sock();
return 0;
}
With the Winsocket tucked away in the struct:
#pragma once
#pragma comment(lib, "ws2_32.lib")
#include <iostream>
#include <vector>
#include <winsock2.h>
#include <WS2tcpip.h>
struct DATA {
std::vector<char*>* content;
int size;
};
struct easy_win_sock {
char *ip;
char *port;
WSADATA *wsaData;
addrinfo* result = nullptr;
addrinfo* ptr = nullptr;
SOCKET *sock;
easy_win_sock(char* ip, char* port) {
this->ip = ip;
this->port = port;
this->sock = new SOCKET;
this->wsaData = new WSADATA;
}
void init_win_sock() {
int i_result = WSAStartup(MAKEWORD(2, 2), wsaData);
if (i_result != 0) {
std::cout << "WASStartup failed: " << i_result << std::endl;
exit(1);
}
}
void create_win_sock() {
this->result = NULL;
this->ptr = NULL;
addrinfo hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// get ip adress of hostname
int i_result = getaddrinfo(this->ip, this->port, &hints, &this->result);
if (i_result != 0) {
std::cout << "getaddrinfo failed: " << i_result << std::endl;
WSACleanup();
exit(1);
}
// create socket
*this->sock = INVALID_SOCKET;
// Attempt to connect to the first adress returned by the call to getaddrinfo
this->ptr = this->result;
// create socket for connecting to server
*this->sock = socket(this->ptr->ai_family, this->ptr->ai_socktype, this->ptr->ai_protocol);
if (*this->sock == INVALID_SOCKET) {
std::cout << "Error at socket(): " << WSAGetLastError() << std::endl;
freeaddrinfo(this->result);
WSACleanup();
exit(1);
}
}
void connect_win_sock() {
// connect to server
int i_result = connect(*this->sock, this->ptr->ai_addr, (int)this->ptr->ai_addrlen);
if (i_result == SOCKET_ERROR) {
closesocket(*this->sock);
*this->sock = INVALID_SOCKET;
}
// if connection failed we just close everithing instead of trying other adresses from getadressinfo()
freeaddrinfo(result);
if (*this->sock == INVALID_SOCKET) {
std::cout << "Unable to connect to server!" << std::endl;
WSACleanup();
exit(1);
}
}
void send_win_sock(char* data, int buf_len) {
int i_result = send(*this->sock, data, buf_len, 0);
if (i_result == SOCKET_ERROR) {
std::cout << "Send failed: " << WSAGetLastError() << std::endl;
closesocket(*this->sock);
WSACleanup();
exit(1);
}
}
DATA* recieve_win_sock_text(int buf_size) {
std::vector<char*>* recvbufs = new std::vector<char*>;
DATA* data = new DATA;
// recieve data till server closes connection
int i_result = 1; // number of recieved bytes
while (i_result > 0) {
recvbufs->push_back(new char[buf_size]);
i_result = recv(*this->sock, (*recvbufs)[recvbufs->size() - 1], buf_size - 1, 0);
if (i_result >= 0) {
(*recvbufs)[recvbufs->size() - 1][i_result] = '\0';
std::cout << (*recvbufs)[recvbufs->size() - 1];
}
else {
std::cout << "recv failed: " << WSAGetLastError() << std::endl;
}
}
data->content = recvbufs;
return data;
}
void cleanup_win_sock() {
// shutdown the connection for sending
// still can recieve
int i_result = shutdown(*this->sock, SD_SEND);
if (i_result == SOCKET_ERROR) {
std::cout << "Shutdown failed: " << WSAGetLastError() << std::endl;
closesocket(*this->sock);
WSACleanup();
exit(0);
}
closesocket(*this->sock);
WSACleanup();
delete this->sock;
delete this->wsaData;
}
};
I am using http://ptsv2.com/ to try out my HTTP requests and on this site they work. When I however try to send a GET request to the site prnt.sc/111111 I get different Error codes depending on my GET request. When I just do a
GET /111111 HTTP/1.1
Host: prnt.sc
<empty line>
for example, I get a 403 Forbidden.
When I use the Website https://reqbin.com/ to test HTTP requests and i put in prnt.sc/111111 it generates the same request but the response it shows is 200 OK.
Can anyone help me? I'm seriously stuck here.
Thanks in advance.

How to receive multiple files through TCP and save them at the same time in C++?

I'm trying to create an app which would accept many connections from clients at the same time and it works for me, but it also should download those files at the same time. In this version of server, even if clients are connected simultaneously, files are written one by one.
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <ctime>
#pragma comment(lib, "ws2_32.lib")
int main()
{
WSADATA wsaData;
int winsock_result = WSAStartup(MAKEWORD(2,2), &wsaData);
if(winsock_result != 0)
{
exit(1);
}
SOCKET server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(server_socket == INVALID_SOCKET)
{
WSACleanup();
exit(1);
}
int const max_clients = 100;
int client_socket[max_clients];
for (int i = 0; i < max_clients; i++)
{
client_socket[i] = 0;
}
char* ip_address = "127.0.0.1";
int port = 6666;
SOCKADDR_IN server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(ip_address);
int server_sizeof = sizeof(server);
int opt = TRUE;
if( setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0 )
{
closesocket(server_socket);
WSACleanup();
exit(1);
}
if(bind(server_socket,(SOCKADDR *)&server, server_sizeof) == SOCKET_ERROR)
{
closesocket(server_socket);
WSACleanup();
exit(1);
}
if(listen(server_socket, 5) == SOCKET_ERROR)
{
std::cout << "Nasluchiwanie portu nieudane." << std::endl;
}
else
{
std::cout << "Nasluchiwanie portu " << port << " udane." << std::endl << std::endl;
}
int const buffer_size = 512;
char buffer[buffer_size];
int max_socket_descriptor, socket_descriptor;
int downloaded_files = 1;
fd_set readfds;
while(true)
{
FD_ZERO(&readfds);
FD_SET(server_socket, &readfds);
max_socket_descriptor = server_socket;
for (int i = 0 ; i < max_clients ; i++)
{
socket_descriptor = client_socket[i];
if(socket_descriptor > 0)
{
FD_SET( socket_descriptor, &readfds);
}
if(socket_descriptor > max_socket_descriptor)
{
max_socket_descriptor = socket_descriptor;
}
}
if ((select( max_socket_descriptor + 1, &readfds, NULL, NULL, NULL) < 0) && (errno != EINTR))
{
std::cout << "Blad funkcji select." << std::endl;
}
if (FD_ISSET(server_socket, &readfds))
{
int new_sockfd;
if ((new_sockfd = accept(server_socket,(SOCKADDR *)&server, &server_sizeof)) == SOCKET_ERROR)
{
std::cout << "Otrzymanie deskryptora nieudane." << std::endl;
}
else
{
for (int i = 0; i < max_clients; i++)
{
if( client_socket[i] == 0 )
{
client_socket[i] = new_sockfd;
std::cout << "Dodawanie do listy socketow jako numer " << i << std::endl;
break;
}
}
}
}
for (int i = 0; i < max_clients; i++)
{
socket_descriptor = client_socket[i];
if (FD_ISSET( socket_descriptor, &readfds))
{
struct sockaddr_in client_address;
char filename[buffer_size];
std::stringstream ip_filename;
ip_filename << "plik" << downloaded_files << "_" << inet_ntoa(client_address.sin_addr);
strcpy(filename, ip_filename.str().c_str());
std::cout << "Nazwa pliku (IP klienta): " << filename << std::endl;
FILE* file;
file = fopen(filename, "wb");
const clock_t begin_time = clock();
int received_size;
do
{
memset(buffer, 0, buffer_size);
received_size = recv(socket_descriptor, buffer, buffer_size, 0);
if (received_size == 0 || received_size == -1)
{
break;
}
fwrite(buffer, sizeof(char), received_size, file);
}
while (received_size != 0);
fclose(file);
std::cout << "Czas wysylania pliku: " << float( clock () - begin_time ) / CLOCKS_PER_SEC << " sekund." << std::endl << std::endl;
closesocket(socket_descriptor);
client_socket[i] = 0;
downloaded_files++;
}
}
}
closesocket(server_socket);
WSACleanup();
system("pause");
return 0;
}
What should I do to make them write many at the same time? I've tried many modifications of the code above but every time I can't get wanted result.
For example:
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <ctime>
#pragma comment(lib, "ws2_32.lib")
int main()
{
WSADATA wsaData;
int winsock_result = WSAStartup(MAKEWORD(2,2), &wsaData);
if(winsock_result != 0)
{
exit(1);
}
SOCKET server_socket;
server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(server_socket == INVALID_SOCKET)
{
WSACleanup();
exit(1);
}
int const max_clients = 100;
int client_socket[max_clients];
for (int i = 0; i < max_clients; i++)
{
client_socket[i] = 0;
}
char* ip_address = "127.0.0.1";
int port = 6666;
SOCKADDR_IN server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(ip_address);
int server_sizeof = sizeof(server);
int opt = TRUE;
if( setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)) < 0 )
{
closesocket(server_socket);
WSACleanup();
exit(1);
}
if(bind(server_socket,(SOCKADDR *)&server, server_sizeof) == SOCKET_ERROR)
{
closesocket(server_socket);
WSACleanup();
exit(1);
}
if(listen(server_socket, 5) == SOCKET_ERROR)
{
std::cout << "Nasluchiwanie portu nieudane." << std::endl;
}
else
{
std::cout << "Nasluchiwanie portu " << port << " udane." << std::endl << std::endl;
}
int const buffer_size = 512;
char buffer[buffer_size];
int max_socket_descriptor;
int downloaded_files = 1;
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(server_socket, &readfds);
max_socket_descriptor = server_socket;
while(true)
{
if ((select( max_socket_descriptor + 1, &readfds, NULL, NULL, NULL) < 0) && (errno != EINTR))
{
std::cout << "Blad funkcji select." << std::endl;
}
for (int i = 0 ; i < max_clients ; i++)
{
if(FD_ISSET(server_socket, &readfds))
{
int new_sockfd;
if ((new_sockfd = accept(server_socket,(SOCKADDR *)&server, &server_sizeof)) == SOCKET_ERROR)
{
std::cout << "Otrzymanie deskryptora nieudane." << std::endl;
}
else
{
for (int i = 0; i < max_clients; i++)
{
if( client_socket[i] == 0 )
{
client_socket[i] = new_sockfd;
FD_SET( client_socket[i], &readfds);
if(client_socket[i] > max_socket_descriptor)
{
max_socket_descriptor = client_socket[i];
}
std::cout << "Dodawanie do listy socketow jako numer " << i << std::endl;
break;
}
}
}
}
if(FD_ISSET(client_socket[i], &readfds))
{
struct sockaddr_in client_address;
char filename[buffer_size];
std::stringstream ip_filename;
ip_filename << "plik" << downloaded_files << "_" << inet_ntoa(client_address.sin_addr);
strcpy(filename, ip_filename.str().c_str());
std::cout << "Nazwa pliku (IP klienta): " << filename << std::endl;
FILE* file;
memset(buffer, 0, buffer_size);
int received_size;
received_size = recv(client_socket[i], buffer, buffer_size, 0);
if (received_size <= 0)
{
closesocket(client_socket[i]);
FD_CLR(client_socket[i], &readfds);
client_socket[i] = 0;
break;
}
else
{
file = fopen(filename, "ab");
fwrite(buffer, sizeof(char), received_size, file);
fclose(file);
}
downloaded_files++;
}
}
}
closesocket(server_socket);
WSACleanup();
system("pause");
return 0;
}
I thought about opening and closing those files every received packet and appending every packet to them, but I really don't have idea how to do it. The example of modified code was meant to do it, but it doesn't work.
I'm forbidden to use other processes and threads than the main one, so I'm kinda helpless now. Thanks for your help.
You have the basic loop with select in place, which is good.
accept is already (mostly) non-blocking. You just need to turn on non-blocking mode on the client sockets and then you'll be able to handle multiple client reads, writes and accepts in your main select loop.
You can have a vector of client-specific data per client, with each entry containing the client socket, the opened file and any other client-specific state.
After the accept, you create a new client entry and add it to the vector. Then in the main loop you do FD_SET for accept and all client's reads and writes. After the select, you inspect the the FD sets and handle them one by one. For best performance you will want your file I/O also in non-blocking mode, but for this assignment that's probably overkill.

How to send any file (image, exe) through UDP in C++?

I'm trying to implement transmission of files through UDP protocol in C++.
What I've got is the server which can send a file requested by a client, but it only works for .txt files. When I try to do the same with image or executable, the transmission corrupts and the file is about 0 KB.
Server:
#include <winsock2.h>
#include <stdio.h>
#include <iostream>
#include <sstream>
#pragma comment(lib, "ws2_32.lib")
#define cipherKey 'S'
int const bufferSize = 512;
char buffer[bufferSize];
void clearBuf(char* b)
{
int i;
for (i = 0; i < bufferSize; i++)
b[i] = '\0';
}
char* notFound = "File not found.";
char Cipher(char ch)
{
return ch ^ cipherKey;
}
int sendFile(FILE* file, char* buffer, int s)
{
int i, len;
if (file == NULL)
{
strcpy(buffer, notFound);
len = strlen(notFound);
buffer[len] = EOF;
return 1;
}
char ch, ch2;
for (i = 0; i < s; i++)
{
ch = fgetc(file);
ch2 = Cipher(ch);
buffer[i] = ch2;
if (ch == EOF)
return 1;
}
return 0;
}
int main()
{
WSADATA wsaData;
int wynik_winsock = WSAStartup(MAKEWORD(2,2), &wsaData);
if(wynik_winsock != 0)
{
exit(1);
}
SOCKET socketServer;
socketServer = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(socketServer == INVALID_SOCKET)
{
WSACleanup();
exit(1);
}
char* ipAdd = "127.0.0.1";
int port = 1234;
SOCKADDR_IN server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(ipAdd);
if(bind(socketServer, (SOCKADDR *)&server, sizeof(server)) == SOCKET_ERROR)
{
closesocket(socketServer);
WSACleanup();
exit(1);
}
std::cout << "Waiting." << std::endl;
SOCKADDR_IN client;
int len_client = sizeof(client);
FILE* file;
if(recvfrom(socketServer, buffer, bufferSize, 0, (SOCKADDR *)&client, &len_client) == SOCKET_ERROR) //Odbiór danych od clienta wraz z kontrolą błędów.
{
closesocket(socketServer);
WSACleanup();
exit(1);
}
else
{
file = fopen(buffer, "rb");
std::cout << "Filename: " << buffer << std::endl;
if(file == NULL)
{
std::cout << "Couldnt open a file." << std::endl;
}
else
{
while (true)
{
if(sendFile(file, buffer, bufferSize))
{
sendto(socketServer, buffer, bufferSize, 0, (SOCKADDR *)&client, len_client);
break;
}
sendto(socketServer, buffer, bufferSize, 0, (SOCKADDR *)&client, len_client);
clearBuf(buffer);
}
fclose(file);
}
}
closesocket(socketServer);
WSACleanup();
system("pause");
return 0;
}
Client:
#include <winsock2.h>
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <string.h>
#pragma comment(lib, "ws2_32.lib")
#define cipherKey 'S'
int const bufferSize = 512;
char buffer[bufferSize];
void clearBuf(char* b)
{
int i;
for (i = 0; i < bufferSize; i++)
b[i] = '\0';
}
char Cipher(char ch)
{
return ch ^ cipherKey;
}
int recvFile(char* buffer, int s, FILE* file)
{
int i;
char ch;
for (i = 0; i < s; i++)
{
ch = buffer[i];
ch = Cipher(ch);
if (ch == EOF)
{
return 1;
}
else
{
fprintf(file, "%c", ch);
}
}
return 0;
}
int main()
{
WSADATA wsaData;
int wynik_winsock = WSAStartup(MAKEWORD(2,2), &wsaData);
if(wynik_winsock != 0)
{
exit(1);
}
SOCKET socketClient;
socketClient = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(socketClient == INVALID_SOCKET)
{
WSACleanup();
exit(1);
}
char* ipAdd = "127.0.0.1";
int port = 1234;
SOCKADDR_IN server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(ipAdd);
int serverSizeOf = sizeof(server);
std::cout << "Name of file to send: ";
std::cin >> buffer;
if(sendto(socketClient, buffer, bufferSize, 0, (SOCKADDR *)&server, serverSizeOf) == SOCKET_ERROR)
{
closesocket(socketClient);
WSACleanup();
exit(1);
}
FILE* file;
file = fopen(buffer, "ab");
while (true)
{
clearBuf(buffer);
if(recvfrom(socketClient, buffer, bufferSize, 0, (SOCKADDR *)&server, &serverSizeOf) == SOCKET_ERROR)
{
closesocket(socketClient);
WSACleanup();
exit(1);
}
if (recvFile(buffer, bufferSize, file))
{
break;
}
fclose(file);
}
closesocket(socketClient);
WSACleanup();
system("pause");
return 0;
}
To do what I said above, I used the tutorial: C program for file Transfer using UDP (Linux).
How can I adapt the code to send other files than .txt only? Thank you in advance.
As said in the comments above you need a data type where EOF has a different value from all other character values, char is inadequate in this respect, especially when you are dealing with binary data.
The following change should improve things
int sendFile(FILE* file, char* buffer, int s)
{
...
for (i = 0; i < s; i++)
{
int ch = fgetc(file);
if (ch == EOF)
return 1;
buffer[i] = Cipher(ch);
}
...
I've decided to change nearly everything in the original solution I tried to implement. The most important changes are reading file using fread and writing it using fwrite.
The file is send in parts of 512 bytes (or less) and those parts are counted in the variable.
If the file requested by a client doesn't exist on the server, special information is sent and the file created to save data is deleted.
Now the program works as expected even for executables and SHA256 of both files, original and received, are the same.
Server:
//SERVER
#include <winsock2.h>
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <ctime>
#pragma comment(lib, "ws2_32.lib")
int main()
{
WSADATA wsaData;
int winsock_result = WSAStartup(MAKEWORD(2,2), &wsaData);
if(winsock_result != 0)
{
exit(1);
}
SOCKET server_socket;
server_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(server_socket == INVALID_SOCKET)
{
WSACleanup();
exit(1);
}
char* ip_address = "127.0.0.1";
int port = 6666;
SOCKADDR_IN server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(ip_address);
if(bind(server_socket,(SOCKADDR *)&server, sizeof(server)) == SOCKET_ERROR)
{
closesocket(server_socket);
WSACleanup();
exit(1);
}
std::cout << "Waiting for data." << std::endl;
SOCKADDR_IN client;
int client_sizeof = sizeof(client);
int const buffer_size = 512;
char buffer[buffer_size];
if(recvfrom(server_socket, buffer, buffer_size, 0,(SOCKADDR *)&client, &client_sizeof) == SOCKET_ERROR)
{
closesocket(server_socket);
WSACleanup();
exit(1);
}
else
{
FILE* file;
file = fopen(buffer, "rb");
std::cout << "Filename: " << buffer << std::endl;
if(file == NULL)
{
std::cout << "Couldn't open the file." << std::endl;
strcpy(buffer, "NOFILE");
if(sendto(server_socket, buffer, buffer_size, 0,(SOCKADDR *)&client, client_sizeof) == SOCKET_ERROR)
{
fclose(file);
closesocket(server_socket);
WSACleanup();
exit(1);
}
}
fseek(file, 0, SEEK_END);
int file_size = ftell(file);
size_t reading_size;
int part = 0;
const clock_t begin_time = clock();
while((part * buffer_size) < file_size)
{
fseek(file, (part * buffer_size), SEEK_SET);
reading_size = fread(buffer, 1, buffer_size, file);
if(sendto(server_socket, buffer, reading_size, 0,(SOCKADDR *)&client, client_sizeof) == SOCKET_ERROR)
{
fclose(file);
closesocket(server_socket);
WSACleanup();
exit(1);
}
part++;
}
std::cout << "Sent " << part << " parts of " << buffer_size << " bytes." << std::endl;
std::cout << "Time of sending file: " << float( clock () - begin_time ) / CLOCKS_PER_SEC << " seconds." << std::endl;
strcpy(buffer, "QUIT");
if(sendto(server_socket, buffer, buffer_size, 0,(SOCKADDR *)&client, client_sizeof) == SOCKET_ERROR)
{
fclose(file);
closesocket(server_socket);
WSACleanup();
exit(1);
}
fclose(file);
}
closesocket(server_socket);
WSACleanup();
system("pause");
return 0;
}
Client:
//CLIENT
#include <winsock2.h>
#include <stdio.h>
#include <iostream>
#include <sstream>
#include <string.h>
#pragma comment(lib, "ws2_32.lib")
int main()
{
WSADATA wsaData;
int winsock_result = WSAStartup(MAKEWORD(2,2), &wsaData);
if(winsock_result != 0)
{
exit(1);
}
SOCKET client_socket;
client_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(client_socket == INVALID_SOCKET)
{
WSACleanup();
exit(1);
}
char* ip_address = "127.0.0.1";
int port = 6666;
SOCKADDR_IN server;
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr.s_addr = inet_addr(ip_address);
int server_sizeof = sizeof(server);
int const buffer_size = 512;
char buffer[buffer_size];
std::cout << "Name of the requested file: ";
std::cin >> buffer;
char filename[buffer_size];
strcpy(filename, buffer);
if(sendto(client_socket, buffer, buffer_size, 0,(SOCKADDR *)&server, server_sizeof) == SOCKET_ERROR)
{
closesocket(client_socket);
WSACleanup();
exit(1);
}
FILE* file;
file = fopen(filename, "wb");
int received_size = 0;
while(true)
{
received_size = recvfrom(client_socket, buffer, buffer_size, 0,(SOCKADDR *)&server, &server_sizeof);
if(received_size == SOCKET_ERROR)
{
fclose(file);
closesocket(client_socket);
WSACleanup();
exit(1);
}
if(strcmp(buffer, "NOFILE") == 0)
{
std::cout << "The file does not exist on the server." << std::endl;
fclose(file);
remove(filename);
break;
}
else if(strcmp(buffer, "QUIT") == 0)
{
std::cout << "Transmission ended by the server." << std::endl;
break;
}
fwrite(buffer, sizeof(char), received_size, file);
}
fclose(file);
closesocket(client_socket);
WSACleanup();
system("pause");
return 0;
}

application/zip winsock c++

I'm trying to make a GET url request, response content type is "application/zip," but I'm having trouble outputting the content to an appropriate/readable zip file, here is my code, as you can tell, I'm trying to write out to 2 different files, neither are working, both are unreadable as zip files:
bool ionMyPlugin::downloadRact(int goodsId) {
goodsId = 36028;
WSADATA wsaData;
SOCKET Socket;
SOCKADDR_IN SockAddr;
int lineCount = 0;
int rowCount = 0;
struct hostent *host;
locale local;
char buffer[10000];
int i = 0;
int nDataLength;
string website_HTML;
// website url
string url = "eihome.eihoo.com";// / api ? mod = rayvr&app = apigoods&act = index&store_id = 34837 & secret_key = 8d410f7007b47e76c227cfa8c282c5f5&add_time = 1474877868 & company = eihome%E6%B5 % 8B % E8%AF % 95 % E4%BC % 81 % E4%B8 % 9A & sign = fd53cce56c4eb88e356d58f19c337e79";
string url2 = "?mod=rayvr&app=apigoods&act=download&store_id=34837&goods_id=36010&secret_key=8d410f7007b47e76c227cfa8c282c5f5&add_time=1474877868&company=eihome%E6%B5%8B%E8%AF%95%E4%BC%81%E4%B8%9A&sign=fd53cce56c4eb88e356d58f19c337e79";// +goodsId;
//HTTP GET
string get_http = "GET /" + url2 + " HTTP/1.1\r\nHost: " + url + "\r\nConnection: close\r\n\r\n";
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0){
cout << "WSAStartup failed.\n";
system("pause");
}
Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
host = gethostbyname(url.c_str());
SockAddr.sin_port = htons(80);
SockAddr.sin_family = AF_INET;
SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr);
if (connect(Socket, (SOCKADDR*)(&SockAddr), sizeof(SockAddr)) != 0){
cout << "Could not connect";
system("pause");
}
// send GET / HTTP
send(Socket, get_http.c_str(), strlen(get_http.c_str()), 0);
ofstream myfile;
fstream myfile2("myfile2.zip", ios::out | ios::binary);
myfile.open("example.zip", std::ios_base::binary);
// recieve html
int countWS = 0;
while ((nDataLength = recv(Socket, buffer, 10000, 0)) > 0){
int i = 0;
while (buffer[i]){//buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r'){
myfile << buffer[i];
myfile2.write(reinterpret_cast<char *> (&buffer[i]), sizeof(buffer[i]));
website_HTML += buffer[i];// >> 8);
//website_HTML += ((buffer[i] << 8) >> 8);
i += 1;
if (i >= nDataLength)
break;
}
}
closesocket(Socket);
WSACleanup();
return false;
}
You may check this example :
#include <string>
#include <stdio.h>
#include <winsock2.h>
#define BUFFER_LEN (4096)
using std::string;
int main(int argc, char **argv)
{
HANDLE fhand;
string request;
int sendret;
int iRecv;
int iResponseLength=0;
int offset;
DWORD dw;
string res2;
char recvBuffer[BUFFER_LEN]={0};
string response;
const char lb[]="\r\n\r\n";
const char http[]="http\x3a//";
const char snsn[]="%s\n";
bool error1=false;
bool error2=false;
bool error3=false;
int len3=strlen(argv[3]);
printf(snsn,"\n-=[ httpget v1.0 by Avery Tarasov");
printf(snsn,"-=[ Email: c0ldshadow#deeptide.com");
printf(snsn,"-=[ Web: www.DeepTide.com");
printf(snsn,"-=[ Dedicated to my fiance, Ostine!\n");
printf(snsn,"Example usage: httpget theserver.com /somefolder/somefile.zip C:\\savehere.zip");
if(argc!=4)
{
printf(snsn,"\nInvalid usage");
goto cleanup;
}
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
{
printf(snsn,"\nError initializing Winsock 2.2");
goto cleanup;
}
error1=true;
if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2)
{
printf(snsn,"\nWinsock 2.2 not available");
goto cleanup;
}
printf(snsn,"\nWinsock 2.2 initialized via wsa2_32.dll");
struct hostent *h;
struct sockaddr_in sa;
SOCKET server1;
h=gethostbyname(argv[1]);
if(h==0)
{
printf(snsn,"\ngethostbyname() failed");
goto cleanup;
}
printf("%s","\nHost lookup succeeded for ");
printf(snsn,argv[1]);
memcpy((char *)&sa.sin_addr,(char *)h->h_addr,sizeof(sa.sin_addr));
sa.sin_family=h->h_addrtype;
sa.sin_port=htons(80);
server1=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(server1==INVALID_SOCKET)
{
printf(snsn,"\nsocket() failed");
goto cleanup;
}
error1=false;
error2=true;
if(connect(server1,(struct sockaddr *)&sa,sizeof(sa))<0)
{
printf(snsn,"\nconnect() failed");
goto cleanup;
}
printf("%s","\nNow connected to ");
printf("%s",argv[1]);
printf(snsn," via port 80");
request+="GET ";
request+=argv[2];
request+=" HTTP/1.0";
request+=&lb[2];
request+="Host: ";
request+=argv[1];
request+=lb;
printf(snsn,"\nHTTP request constructed successfully:\n");
printf(snsn,request.c_str());
sendret=send(server1,request.c_str(),request.length(),0);
if(sendret==-1)
{
printf(snsn,"send() failed");
goto cleanup;
}
printf(snsn,"Successfully sent HTTP request to the server");
printf(snsn,"\nWaiting for download to complete");
fhand=CreateFile(argv[3],GENERIC_WRITE,FILE_SHARE_READ,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
if(fhand==INVALID_HANDLE_VALUE)
{
printf(snsn,"\nCreateFile() failed");
goto cleanup;
}
error2=false;
error3=true;
while((iRecv=recv(server1,recvBuffer,BUFFER_LEN-1,0))>0)
{
/*
char hex[5];
string packet;
packet.reserve(5*iRecv);
printf(snsn,"\n");
printf("%s","Receiving ");
printf("%d",iRecv);
printf(snsn," byte packet:\n");
for(int i=0;i<iRecv;++i)
{
wsprintf(hex,"%02x",(unsigned char)recvBuffer[i]);
packet.append(hex);
printf("%s ",hex);
}
*/
response.append(recvBuffer,iRecv);
iResponseLength+=iRecv;
ZeroMemory(recvBuffer,BUFFER_LEN);
}
if(iRecv==SOCKET_ERROR)
{
printf(snsn,"\n\nrecv() failed");
}
offset=response.find(lb)+4;
if(offset!=string::npos)
{
printf("%s","\n\nFile starts at offset ");
printf("%d\n",offset);
printf(snsn,"\nInitial response from server:\n");
for(int j=0;j<offset;++j)
{
printf("%c",response[j]);
}
res2.assign(response,offset,response.size());
if(WriteFile(fhand,res2.data(),res2.size(),&dw,0)==0)
{
printf(snsn,"\nWriteFile() failed");
goto cleanup;
}
else
{
printf("%s","\nFile successfully downloaded and saved to ");
printf(snsn,argv[3]);
}
}
cleanup:
if(error1)
{
WSACleanup();
}
if(error2)
{
WSACleanup();
closesocket(server1);
}
if(error3)
{
WSACleanup();
closesocket(server1);
CloseHandle(fhand);
}
return 0;
}

Download data from Wikipedia page

I'm trying to download data from Wikipedia. I send a GET request, but the return status - "HTTP 301 redirection". Now I need to parse that to get the target URL, and from there I can access the article content.
I do the parse but but I cannot access to the article content. I appreciate your help if you can help me to get to the article content.
code -
#include <winsock2.h>
#include <WS2tcpip.h>
#include <windows.h>
#include <iostream>
#include <vector>
#include <ostream>
using namespace std;
int main(){
string query = "Google";
//int depth = 0;
// Initialize Dependencies to the Windows Socket.
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
cout << "WSAStartup failed.\n";
system("pause");
}
struct addrinfo hints;
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_socktype = SOCK_STREAM;
/* connect to wikipedia //and download the article */
static const char wiki_host[] = "en.wikipedia.org";
struct addrinfo* targetAdressInfo = NULL;
DWORD getAddrRes = getaddrinfo(wiki_host, NULL, &hints, &targetAdressInfo);
if (getAddrRes != 0 || targetAdressInfo == NULL)
{
cout << "Could not resolve the Host Name" << endl;
system("pause");
WSACleanup();
return -1;
}
SOCKADDR_IN sockAddr;
sockAddr.sin_addr = ((struct sockaddr_in*) targetAdressInfo->ai_addr)->sin_addr;
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons(80);
freeaddrinfo(targetAdressInfo);
SOCKET webSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (webSocket == INVALID_SOCKET)
{
cout << "Creation of the Socket Failed" << endl;
system("pause");
WSACleanup();
return -1;
}
if (connect(webSocket, (SOCKADDR*)&sockAddr, sizeof(sockAddr)) != 0)
{
cout << "Could not connect";
system("pause");
closesocket(webSocket);
WSACleanup();
return -1;
}
string http_query = "GET /wiki/" + query + " HTTP/1.1\r\n";
http_query += string("Host: ") + wiki_host + "\r\n";
http_query += "\r\n\r\n";
if (send(webSocket, http_query.c_str(), http_query.length(), 0) == -1) {
cout << "Could not send the request to the Server" << endl;
system("pause");
closesocket(webSocket);
WSACleanup();
return -1;
}
/* prepare to fetch the wiki article */
string response = "";
while (true) {
static char recv_buffer[4096];
const int bytes_read = recv(webSocket, recv_buffer, sizeof(recv_buffer) - 1, 0);
if (!bytes_read) {
break;
}
if (bytes_read == -1) {
closesocket(webSocket);
WSACleanup();
}
recv_buffer[bytes_read] = '\0';
response += recv_buffer;
};
/* finished with the socket */
closesocket(webSocket);
WSACleanup();
/* parse the http response headers */
size_t cursor = 0;
string response_content;
vector<std::string> response_headers;
const size_t headers_end = response.find("\r\n\r\n");
while (true) {
const size_t line_end = response.find("\r\n", cursor);
if (line_end == std::string::npos) { /* probably due to http error */
break;
}
response_headers.push_back(response.substr(cursor, line_end - cursor));
if (line_end == headers_end) { /* found content */
response_content = response.substr(headers_end + 4); /* skip \r\n\r\n */
break;
}
cursor = line_end + 2; /* skip \r\n */
}
// print the respone
for (int i = 0; i < sizeof(response); i++){
cout << response[i];
}
/* print response_content not work
for (int i = 0; i < sizeof(response); i++){
cout << response_content[i];
}*/
system("pause");
return 0;
}
I'm not sure what you mean by saying "I do the parse but but I cannot access to the article content". What you need to do when you get 301 status is to look at "Location" header you received back. That header contains the URL you can use to fetch the content you are looking for.