简体   繁体   English

带有套接字的原始HTTP请求“资源暂时不可用”

[英]Raw HTTP request with sockets getting “Resource temporarily unavailable”

I am trying to make a raw http request function using sockets in "C++". 我正在尝试使用“ C ++”中的套接字制作原始的http请求功能。 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 . 当我在没有打开80的ip上发出请求时,它永远存在,因此我决定进行超时,因此开始使用blocking套接字,而我开始使用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. 我在http服务器上收到了请求,但从未收到响应。 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. 已经在浏览器中进行了测试,wget,curl,似乎问题在于它没有进入while(recv(sock, buf, 8192, 0) > 0)循环,但是正在发出请求。 It gives me Resource temporarily unavailable basically. 它使我的Resource temporarily unavailable基本上Resource temporarily unavailable

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); 我做了一个fcntl(sock, F_SETFL); after the if(select(sock + 1, NULL, &fdset, NULL, &tv) == 1) ... part and i still get no content if(select(sock + 1, NULL, &fdset, NULL, &tv) == 1) ...我仍然没有任何内容

You may not omit the third arg of the fcntl(sock, F_SETFL, …) call; 您可能不会忽略fcntl(sock, F_SETFL, …)调用的第三个参数 to remove the O_NONBLOCK flag, you can call fcntl(sock, F_SETFL, 0) . 要删除O_NONBLOCK标志,可以调用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. 此外,在非阻塞的第一个connect产生“ Operation”(正在进行操作)之后,您可能不会省略第二个connect呼叫,因此请删除第二个呼叫周围的注释。

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. 已经接收到网页内容的第一块(如果足够小,则接收全部内容),但是您将丢弃buf ,而不显示接收到的内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM