代码之家  ›  专栏  ›  技术社区  ›  adhanlon

recv()上的http客户端块

  •  0
  • adhanlon  · 技术社区  · 16 年前

    我需要一些关于编写http客户端的帮助。当我试图从Web服务器接收数据时,麻烦就来了。recv()调用将阻止该程序。任何更好的方向都会非常有用,我将在下面发布我的代码:

    if ( argc != 2 )
    {
        cerr << "Usage: " << argv[0];
        cerr << " <URI>" << endl;
        return 1;
    }
    else
    {
        uri_string = argv[1];
    }
    
    // Create URI object and have it parse the uri_string
    URI *uri = URI::Parse(uri_string);
    
    if ( uri == NULL )
    {
        cerr << "Error: Cannot parse URI." << endl;
        return 2;
    }
    
    // Check the port number specified, if none use port 80
    unsigned port = 80;
    if ( uri->Is_port_defined() )
    {
        port = uri->Get_port();
    }
    
    // Create TCP socket and connect to server
    int tcp_sock = socket( AF_INET, SOCK_STREAM, 0 );
    if ( tcp_sock < 0 )
    {
        cerr << "Unable to create TCP socket." << endl;
        return 3;
    }
    
    sockaddr_in server;
    socklen_t slen = sizeof(server);
    
    server.sin_family = AF_INET;
    server.sin_port = htons( port );
    hostent *hostp = gethostbyname( uri->Get_host().c_str() );
    memcpy( &server.sin_addr, hostp->h_addr, hostp->h_length );
    
    if ( connect( tcp_sock, (sockaddr*)&server, slen ) < 0 )
    {
        cerr << "Unable to connect to server via TCP." << endl;
        close( tcp_sock );
        return 4;
    }
    
    // Build HTTP request to send to server
    HTTP_Request *request = HTTP_Request::Create_GET_request( uri->Get_path() );
    request->Set_host( uri->Get_host() );
    string request_string = "";
    request->Print( request_string );
    
    //cout << request_string << endl;
    
    // Send it to the server, wait for reply and use HTTP_Response to get reply
    send( tcp_sock, &request_string, sizeof(request_string), 0 );
    
    char recv_buffer[1024];
    int bytes_recv = 0;
    while ( bytes_recv < 1024 )
    {
        int recv_len = recv( tcp_sock, recv_buffer + bytes_recv,
            1024 - bytes_recv, 0 );
        if ( recv_len == -1 )
        {
            cerr << "Error receiving response from server." << endl;
            close( tcp_sock );
            return 5;
        }
        bytes_recv += recv_len;
    }
    
    
    HTTP_Response *response = HTTP_Response::Parse(recv_buffer, bytes_recv);
    string response_string = "";
    response->Print( response_string );
    cout << response_string << endl;
    
    return 0;
    

    }

    5 回复  |  直到 16 年前
        1
  •  3
  •   Remy Lebeau    16 年前

        2
  •  1
  •   Andy Ross    16 年前

    recv() 想象上的 阻止,直到收到响应为止。您确定您正确地编写了请求,并且服务器正在响应它吗?可以将文件描述符置于非阻塞模式,并使用 select() poll() ,但我猜你只是在某个地方有一个协议错误。你期望的行为是什么?

        3
  •  0
  •   Loki Astari    16 年前

    这是个问题吗?

    如果客户是comamnd line,则可以。
    如果是GUI,那么检索数据的线程应该与UI线程不同。

    但解决方法是使用select()命令

    这样你就可以在等待的时候做其他的工作。

        4
  •  0
  •   diciu    16 年前

    HTTP请求应以空行结束,即。


    GET / HTTP/1.1
    Host: blah.com
                        <- this here is an empty line
    

    请求->打印(请求字符串+“\n”)

    离题 :您知道C中有现成的HTTP客户端,对吗(例如libcurl)。

        5
  •  0
  •   robert vano    14 年前

    您必须接收“内容长度”字段中的许多字节。 if ( recv_len == -1 ) 致:

    if ( recv_len <= 0 ) break;
    else if ( recv_len == -1 )
    

    因为0是服务器在发送所有数据后将断开连接的时间。