繁体   English   中英

在recv()上的HTTP客户端块

[英]http client blocks on recv()

我需要一些帮助来编写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;

}

您正在使用阻塞的TCP / IP套接字,但是您没有查看HTTP答复的“ Content-Length”标头来知道要读取多少字节。 您当前的读取逻辑正在循环中调用recv(),直到已接收到最大1024个字节。 如果服务器发送的字节数少于1024个字节,则将无限期地被阻塞,因为调用recv()的次数过多,要求输入的字节数过多。

recv() 应该阻塞直到得到响应。 您确定自己编写的请求正确无误,并且服务器正在响应吗? 可以将文件描述符置于非阻塞模式,并使用select()poll()对其进行测试,但是我的猜测是,您只是在某个地方存在协议错误。 您期望的行为是什么?

这有问题吗?

如果客户是同志,那就行了。
如果是GUI,则线程检索数据应与UI线程不同。

但是解决方案是使用select()
这将告诉您是否要从端口读取任何内容。
因此,您可以在等待时做其他工作。

HTTP请求应以空行结尾,即


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

看来您的代码没有这样做(它可能应该说request-> Print(request_string +“ \\ n”)

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

您必须收到许多字节,即内容长度字段中的内容。 您必须将行: if ( recv_len == -1 )更改为:

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

因为0表示服务器在发送所有数据后将断开连接。

暂无
暂无

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

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