很慢的Winsock2接收 [英] Very Slow Winsock2 recv

查看:87
本文介绍了很慢的Winsock2接收的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好,

我正在用C ++开发一个简单的HTTP客户端(使用VS2010),并且使用位于 localhost 的Apache进行测试.

发送''代码的工作原理像一个超级按钮, recv 最多需要6-7秒才能接收到整个消息(大约500个字节).

实际的问题: recv 为何这么慢? (我也在我的套接字上设置了TCP_NODELAY)

我对接收例程的实现:

Hello,

I''m developing a simple HTTP client in C++ (using VS2010) and I''m using an apache located at localhost for testing.

While the send''ing code workes like a charm, the recv takes up to 6-7 seconds to receive the whole message (500 bytes or so).

The actual question: how come is recv so slow? (I''m also setting TCP_NODELAY on my socket)

My implementation of the receiving routine:

int HttpClient::_receive()
{
    char buffer[1024];
    int  iReceivedBytes = 0;

    // init the buffer to an empty string
    buffer[0] = 0;

    while(1)
    {
        iReceivedBytes = recv(m_socket, buffer, 1024, 0);
        if (iReceivedBytes > 0)
        {
            // m_response is a member std::string
            m_response.append(buffer, iReceivedBytes);
        } else
           break;
    }

    // parse message
    return _parseMessage();
}



使用浏览器测试apache时,不到1秒即可执行相同的请求.

谢谢,
Alex



When testing the apache with a browser it takes less than 1 second to perform the same request.

Thanks,
Alex

推荐答案

TCP_NODELAY仅对发送有效,它对recv()无效.如果您经常在数据量较小的套接字上调用send(),则可以打开/关闭nagle算法,从而更好地使用带宽.

这是我的猜测:当recv()返回零或负数时,您将退出无限循环.这很不好,有两个原因. 负值表示发生了非常糟糕的事情,您应该特别处理.当另一侧的连接已关闭时,recv()返回零(例如,因为http服务器已关闭其套接字).您的问题可能是您正在等待此套接字关闭事件,因此不应依赖它.如果您在请求中使用HTTP 1.0标头,则HTTP会话不会使用永久连接,对于HTTP 1.1,仅在使用 ^ ]标头.但是,即使http会话的连接不是永久的,也没有人保证您服务器在发送数据后关闭该连接.要检查您的问题是否是我所描述的,请执行以下操作:在每个recv()之后,注销接收的字节总数.当您退出循环时,还要打印一条日志消息.我想您会在不到一秒钟的时间内收到所有数据,但是只有在服务器关闭连接后5秒钟后,中断才会执行.

为避免上述问题,您的http客户端应按以下方式工作:当前,您读取了整个包,包括标头和有效负载,并在此之后对其进行解释.相反,您应该首先阅读标头部分-它易于检测,是双换行符(CRLF)-然后应解析/解释标头.如果响应不使用分块的传输编码(由响应中的"Transfer-Encoding:chunked"标头指示),则HTTP响应的有效负载将具有由"Content-Length"标头字段指示的固定大小.我猜您不想处理分块的传输编码,因此您将寻找Content-Length标头.因此,您阅读了标头,并找到了有效负载的大小.之后,您就知道标题后面有多少个字节-您只需从套接字中读取并关闭连接即可.
TCP_NODELAY has effect only on sending, it doesn do anything with recv(). It turns on/off the nagle alorithm that makes bandwith usage better if you call send() on a socket often with small data sizes.

Here is my guess: You exit your infinite loop when recv() returns zero or negative. This is bad for two reasons.
A negative values means that something very bad happened and you should handle it specially. Zero is returned by recv() when the connection has been shut down on the other side - for example because the http server has closed its socket. Your problem is probably that you are waiting for this socket close event and you should not rely on it. If you are using HTTP 1.0 header in your request then your http session isnt using permanent connection, in case of HTTP 1.1 its the same only if you use the Connection: close[^] header in your request. But even if the connection of http session isn''t permanent noone guarantees for you that the server closes the connection after sending the data. To check if your problem is what I described do the following: After every recv() log out the totoal number of bytes received. Also print a log message when you break out from your loop. I guess you receive all data in less than a second, but the break executes only after 5 seconds when the server closes the connection.

To avoid the previous issues your http client should work like this: Currently you read the whole packet including the header and the payload and you interpret it just after this. Instead this you should read only the header part first - its easy to detect it, a double newline (CRLF) - and then you should parse/interpret the header. If the response doesnt use chunked transfer encoding (indicated by the "Transfer-Encoding: chunked" header in the response) then the payload of the HTTP response will have fixed size indicated by the "Content-Length" header field. I guess you dont want to handle chunked transfer encoding so you will look for Content-Length headers instead. So you read the header and found out the size of the payload. After this you know how many bytes following the header - you just read that out from the socket and the close the connection.


这篇关于很慢的Winsock2接收的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆