# [C++] Winsock and blocking recv-calls

This topic is 4764 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hey, how are you doing? I've been working on a webpage fetcher, but I've encountered a problem: when I request a webpage, although the downloading of the page itself takes only two seconds, the last recv (which will be checked for zero to exit) waits 14 seconds to return 0. One way of solving is is to look at the content-length headers, but not every server does reply with a full header. So at some servers, the problem still exists! Mozilla Firefox doesn't have a problem with it and loads every page quickly so it must use some other method than I'm doing. My question: does anybody know how I can change my code so that it doesn't get blocked? (by the way, I couldn't find anything in the msdn documentation, which I also noted to be very ANSI-non-friendly) Here's my code I have so far:
#include <cstdio>           // Needed for printf()
#include <cstdlib>          // Needed for exit()
#include <string.h>         // Needed for strcpy() and strlen()
#include <windows.h>        // Needed for all Winsock stuff

#include <iostream>
using namespace std;

#define  BUF_SIZE            4096     // Buffer size

int main(void)
{
WORD wVersionRequested = MAKEWORD(1,1);    // Stuff for WSA functions
WSADATA wsaData;                           // Stuff for WSA functions

unsigned int         server_s;             // Server socket descriptor
char                 in_buf[BUF_SIZE];     // Input buffer for response
int                  retcode;              // Return code

// This stuff initializes winsock
int test = WSAStartup(wVersionRequested, &wsaData);
if (test != NO_ERROR) {
printf("Error at WSAStartup()\n");
return -1;
}

// Create a socket
server_s = socket(AF_INET, SOCK_STREAM, 0);

if ( server_s == INVALID_SOCKET ) {
printf( "Error at socket(): %d\n", WSAGetLastError() );
WSACleanup();
return -1;
}

char * ip_addr = "80.249.158.5";
int port_num = 6969;

// Fill-in the Web server socket's address information
server_addr.sin_family = AF_INET;                 // Address family to use
server_addr.sin_port = htons(port_num);           // Port num to use

// Do a connect (connect() blocks)
if (retcode != 0)
{
printf("ERROR - connect() failed \n");
WSACleanup();
return -1;
}

char * get_string = "GET /scrape HTTP/1.1\r\n"
"Connection: Keep-Alive\r\n"
"User-Agent: Client\r\n"
"Accept: text/html, image/jpeg, image/png, text/*, image/*, */*\r\n"
"Accept-Encoding: gzip, deflate\r\n"
"Accept-Charset: iso-8859-1, utf-8;q=0.5, *;q=0.5\r\n"
"Accept-Language: en\r\n"
"Host: 80.249.158.5:6969\r\n\r\n";

// Send a GET to the Web server
send(server_s, get_string, strlen(get_string), 0);

// Open file
FILE *fp = fopen( "page.txt", "wb" );

// Receive from the Web server
//  - The return code from recv() is the number of bytes received
cout << "waiting for server" << endl;
retcode = recv(server_s, in_buf, BUF_SIZE, 0);
cout << retcode << "bytes received" << endl;
while ((retcode > 0) || (retcode == -1) && retcode != WSAECONNRESET)
{
if (retcode == -1)
{
printf("ERROR - recv() failed \n");
exit(1);
}
fwrite(in_buf, 1, retcode, fp);

retcode = recv(server_s, in_buf, BUF_SIZE, 0);
cout << retcode << "bytes received" << endl;
}

// Close file
fclose(fp);

// Close all open sockets
closesocket(server_s);

// This stuff cleans-up winsock
WSACleanup();
}


Oh and another thing before I forget: is it advisable to use winsock2 instead of winsock? Now I'm using Winsock but I don't see a lot of difference between the two libs. Cheers, Bas

##### Share on other sites

Do a google search for non blocking sockets, I cant remember of hand how you do it. Its fairly straight forward though.

You should be fine with Winsock 1.1.

##### Share on other sites
It might be straightfoward, but it's not well documented on the Internet. It would be very helpful if someone would show a snipplet of code in which a non blocking socket is set up. That's all I need; I think it's pretty strange that msdn doesn't show how to create a non blocking socket... I have found how to do it in GNU but MS's reference is quite appauling.

Good day,
Bas

##### Share on other sites
You have said that you are writting a web page fetcher. With this is mind, would it not be useful to look into Multi-Threading sockets, which would also solve your recv() call blocking.

Maybe you've already thought of this, its just your code didn't hint at it!

##### Share on other sites
Hey Kalligan. I have solved the recv-blocking problems; it seemed that I had found a bad tutorial on the Internet.... after tweaking a bit I got non-blocking recv. After that, I've started working on threading. I've never heard of mult-threaded sockets and never though about it, but at the moment I've already programmed a large part of the program using the pthread lib and it's working properly.

Bas