I am trying to make a raw http request function using sockets in "C++". Everything worked good until i saw that i don't have timeout on that function, eg. when i do a request on an ip that don't have 80 open, it stays forever, so i decided to make a timeout, there fore instead using blocking
sockets i started using non-blocking
. There is that problem started. See the code bellow :
CODE :
size_t raw_http(char *host,char *ip, int port, char *page, char *content, size_t len)
{
int sock;
if(debug_super_http >= 5) puts("AAAA");
// sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock < 0)
{
if(debug_super_http >= 5) puts("BBBB");
//printf("raw_http() ~ socket opening failed.\n");
// exit(1);
return 0;
}
perror("socket");
struct sockaddr_in remote ;
remote.sin_family = AF_INET;
remote.sin_port = htons(port);
remote.sin_addr.s_addr = inet_addr(ip);
fd_set fdset;
struct timeval tv;
fcntl(sock, F_SETFL, O_NONBLOCK);
if(debug_super_http >= 4) puts("CCCC");
perror("socket");
connect(sock,(struct sockaddr*)(&remote),sizeof(struct sockaddr_in));
perror("socket");
FD_ZERO(&fdset);
FD_SET(sock, &fdset);
tv.tv_sec = 10;
tv.tv_usec = 0;
if(select(sock + 1, NULL, &fdset, NULL, &tv) == 1)
{
int so_error;
socklen_t len = sizeof so_error;
getsockopt(sock, SOL_SOCKET, SO_ERROR, &so_error, &len);
if (so_error == 0)
{
//Is connected
if(debug_super_http >= 4) puts("EEEE");
perror("socket");
}
else
{
if(debug_super_http >= 4) puts("FFFF");
perror("socket");
}
}
else
{
if(debug_super_http >= 4) puts("GGGGG");
perror("socket");
}
/*
if(debug_super_http >= 5) puts("33333");
if(inet_pton(AF_INET, ip, (void *)(&(remote.sin_addr.s_addr))) <= 0)
{
//printf("raw_http() ~ inet_pton() failed.\n");
// exit(1);
return 0;
}
remote.sin_port = htons(port);
*/
if(debug_super_http >= 5) puts("44444");
perror("socket");
/*
if(connect(sock, (struct sockaddr *)&remote, sizeof(struct sockaddr)) < 0)
{
if(debug_super_http >= 5) puts("555555");
//printf("raw_http() ~ socket connection failed.\n");
// exit(1);
return 0;
}
*/
if(debug_super_http >= 5) puts("666666");
//build_get_query
char *getpage = page;
if(getpage[0] == '/') getpage = getpage + 1;
char getcmd[4096];
sprintf(getcmd, "GET /%s HTTP/1.0\r\nHost: %s\r\nUser-Agent: %s\r\n\r\n", getpage, host, USERAGENT);
if(debug_super_http >= 5) puts("7777777");
perror("socket");
size_t sent = 0;
while(sent < strlen(getcmd))
{
if(debug_super_http >= 5) puts("8888888");
perror("socket");
ssize_t tmpres = send(sock, getcmd+sent, strlen(getcmd)-sent, 0);
printf("tmpres=[%d]\n",tmpres);
if(tmpres == -1)
{
// printf("raw_http() ~ http get command sending error.\n");
if(debug_super_http >= 5) puts("8.5 8.5 8.5");
// exit(1);
return 0;
}
sent += tmpres;
if(debug_super_http >= 5) puts("8.7 8.7 8.7");
}
if(debug_super_http >= 5) puts("9999999");
perror("socket");
char buf[8192];
memset(buf, 0, 8192);
// initialize html content buffer
memset(content, 0, len);
/*
#if 0
htmlcontent[0] = '\0';
return 0;
#endif
*/
int htmlstart = 0;
printf("recv->[%d]\n",recv(sock, buf, 8192, 0));
fprintf(stderr, "socket() failed: %s\n", strerror(errno));
perror("socket");
while(recv(sock, buf, 8192, MSG_WAITALL) > 0)
{
// if(debug_super_http >= 5) printf(">>> [%s]\n",buf);
if(debug_super_http >= 5) puts("10 10 10");
// receive max 1KB
if(htmlstart == 0)
{
char *ptr = strstr(buf, "\r\n\r\n");
if(ptr != NULL)
{
htmlstart = 1;
ptr += 4;
strcat(content, ptr);
}
}
else
{
strcat(content, buf);
break;
}
memset(buf, 0, 8192);
}
perror("socket");
if(debug_super_http >= 5) printf(">>> CONTENT >>> [%s]\n",content);
if(debug_super_http >= 5) puts("11 11 11");
close(sock);
if(debug_super_http >= 5) puts("12 12 12");
perror("socket");
return strlen(content);
}
I get the request on the http server, but i never get the response. Have tested it in browsers, wget, curl, seems the problem is that it is not entering the while(recv(sock, buf, 8192, 0) > 0)
loop, but the request is being made. It gives me Resource temporarily unavailable
basically.
OUTPUT :
AAAA
socket: Success
CCCC
socket: Illegal seek
socket: Operation now in progress
EEEE
socket: Illegal seek
44444
socket: Illegal seek
666666
7777777
socket: Illegal seek
8888888
socket: Illegal seek
tmpres=[133]
8.7 8.7 8.7
9999999
socket: Illegal seek
recv->[-1]
socket() failed: Resource temporarily unavailable
socket: Resource temporarily unavailable
socket: Resource temporarily unavailable
>>> CONTENT >>> []
11 11 11
12 12 12
socket: Resource temporarily unavailable
EDIT
puts(getcmd);
is :
GET /script.php?v=qqqqq HTTP/1.0
Host: 1.2.3.4
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; rv:2.2) Gecko/20110201
(here is /r/n/r/n probably)
Any hint?
Thank you!
i did a
fcntl(sock, F_SETFL);
after theif(select(sock + 1, NULL, &fdset, NULL, &tv) == 1) ...
part and i still get no content
You may not omit the third arg of the fcntl(sock, F_SETFL, …)
call; to remove the O_NONBLOCK
flag, you can call fcntl(sock, F_SETFL, 0)
.
In addition, you may not omit the second connect
call after the non-blocking first connect
yielded Operation now in progress , so remove the commenting around the second call.
Furthermore, the line
printf("recv->[%d]\n",recv(sock, buf, 8192, 0));
already receives the first chunk of the web page content (or the entire content if small enough), but you discard what's in buf
and don't display what was received.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.