我需要一些帮助来编写http客户端。当我尝试从网络服务器接收数据时出现问题。 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;
}
答案 0 :(得分:3)
您正在使用阻塞TCP / IP套接字,但您没有查看HTTP回复的“Content-Length”标头以了解要读取的字节数。您当前的读取逻辑在循环中调用recv(),直到收到最大1024字节为止。如果服务器发送的字节数少于1024个,那么您将无限期地被阻塞,因为您调用recv()的次数太多,要求的字节太多。
答案 1 :(得分:1)
recv()
假设要阻止,直到收到回复为止。您确定要正确编写请求,服务器是否正在响应它?可以将文件描述符置于非阻塞模式并使用select()
或poll()
进行测试,但我的猜测是你只是在某个地方有一个协议错误。你期待的行为是什么?
答案 2 :(得分:0)
这是一个问题吗?
如果客户是comamnd线罚款 如果是GUI,那么线程检索数据应该与UI线程不同。
但解决方法是使用select()
这将告诉您是否有任何东西要从端口读取
因此允许你在等待的时候做其他工作。
答案 3 :(得分:0)
HTTP请求应以空行结束,即
GET / HTTP/1.1
Host: blah.com
<- this here is an empty line
看起来您的代码没有这样做(它应该说 request-&gt; Print(request_string +“\ n”)。
偏离主题:你知道C中有很多可用的HTTP客户端,对吗? (例如libcurl)。
答案 4 :(得分:0)
您必须接收内容长度字段中的许多字节。
您必须更改行:if ( recv_len == -1 )
到:
if ( recv_len <= 0 ) break;
else if ( recv_len == -1 )
因为0表示服务器在发送所有数据后将断开连接。