2017-07-12 16 views
-1

問題に焦点を当てて、コード内の小さなファウルをあまり重要視しないでください。接続を終了せずにページ全体を受信

コードは同じページを10回要求します。私はすべてを受け取ったことを確認するために、バッファが0バイトになるまで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)); 
    } 

} 
+2

あなたはあなたが呼び出した関数の戻り値をチェックする必要があります。特に、 'send'と' recv'関数は、エラーがあった場合、その呼び出しでどれくらい送受信されたかを返すので、*または*(これも重要です)。 –

+0

合意して、これを私のメインコードで変更します。しかし、問題についてはどう思いますか?私はそのコードは、それがすべきだが、私のソケットの知識に欠けているものとして動作しているので、そのエラーとは思わない。 – JavaOdd

答えて

1

問題は、ソケットが、その後recvが無期限にブロックします読んで、それが何かを受け取ったか、エラーが検出されたのいずれかになるまで戻らないために何もない場合はそうをブロックしている可能性が最も高いです。

一方、プログラムがrecv機能でブロックされている間、サーバーはタイムアウトして接続を終了します。これにより、プログラム内のrecvがブロック解除され、0が返されます。

同じ接続を使用し続ける場合は、ソケットを非ブロック化する必要があります。recvコールの失敗を確認してください。 recvが正常にブロックすると、エラー(SOCKET_ERROR)が返され、エラーコード(WSAGetLastErrorから)がWSAEWOULDBLOCKに設定されます。

+0

それを実装する方法はわかりませんが、私はベストを尽くしてメインのポストでコードを編集しました。私はそれをテストし、明らかに私は何もエラーを受け取っていない、すべてのrecv私は "操作が成功して完了しました"というメッセージを受け取った。 recvが0バイトを受け取った後で接続が閉じられているとは、エラーではなくコードのデフォルト動作です。 – JavaOdd

+0

@ JavaOddエラーをチェックする前に、関数が実際に失敗したことを確認する必要があります。あなたはそれを確認します。 'recv' *は*を返します。私はあなたが良いものとしてすべてのことを説明している必要がありますいくつかのソケットチュートリアルを見つける必要があると思う。 –

+0

私の知識では、> 0バッファバイト、i = 0は閉じ、iは<0エラーです。リターンであなたがi = recv(e、b、sizeof(b)、0)を意味するならば、それはバッファ内のバイト数を返し、それから複数のゼロが返されます。それは否定/エラーを受け取っていませんでした。あなたが何かを意味するならば、私はチュートリアルを検索します。 – JavaOdd

関連する問題