无需关闭连接即可接收整页

时间:2017-07-12 12:57:33

标签: c++ sockets

请不要过分重视代码中的小犯规,关注问题。

代码请求同一页10次。它调用recv直到缓冲区为零字节,以确保我收到了所有内容。问题是,当recv具有零字节时,它会关闭连接,这意味着我只收到了第一页。我需要在请求下一页之前收到整个页面。

如何接收整个页面并知道它最后一次调用recv而不是去零字节?

#include <iostream>
#include <fstream>
#include <winsock2.h>
#include <time.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
int main() {

    WSADATA w;
    WORD DllVersion = MAKEWORD(2, 1);
    WSAStartup(DllVersion, &w);
    SOCKADDR_IN u = { AF_INET,htons(80),0,0 };
    u.sin_addr.s_addr = inet_addr("1.1.1.1");
    SOCKET e = socket(AF_INET, 0, 0);
    connect(e, (SOCKADDR*)&u, sizeof(u));

    string l="GET / HTTP/1.1\r\nHost:www.site.com\r\nConnection:keep-alive\r\n\r\n";

    char b[100000];
        int i,iResult,iError,error;
    ofstream z("pg.htm");

    for(i=0;i<10;i++){
        send(e, l.c_str(), strlen(l.c_str()), 0);
        do{

            clock_t begin = clock();

            z << b;
            memset(b, 0, sizeof(b));
            int iResult=recv(e, b, sizeof(b), 0);
                if (iResult == SOCKET_ERROR ) {
                        int iError = WSAGetLastError();
                        if (iError == WSAEWOULDBLOCK)
                    printf("recv failed with error: WSAEWOULDBLOCK\n");
                else
                    printf("recv failed with error: %ld\n", iError);
            }

            wchar_t *s=NULL;
            FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,NULL,WSAGetLastError(),MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPWSTR)&s,0,NULL);
            fprintf(stderr,"%S\n",s);
            LocalFree(s);

            clock_t end = clock();
            double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
            cout << time_spent;
            cout << "#";
            cout << iResult;
            cout << "#";

        }while(strlen(b)!=0);
        memset(b, 0, sizeof(b));
    }

}

1 个答案:

答案 0 :(得分:1)

问题很可能是套接字阻塞所以如果没有任何内容可读,那么recv将无限期地阻塞,并且在收到某些内容或检测到错误之前不会返回。 / p>

另一方面,当您的程序在recv功能中被阻止时,服务器将超时并关闭连接。这会导致您的计划中的recv被取消屏蔽并返回0

如果您想继续使用相同的连接,则需要使套接字非阻塞并检查recv调用中的失败。当recv通常会阻止它时会返回错误(SOCKET_ERROR),并将错误代码(从WSAGetLastError获得)设置为WSAEWOULDBLOCK

相关问题