2017-07-19 4 views
1

私はHTTP要求を行うためにwinsockを使用しています。私のサーバー側では、ファイルの内容を取得してbase64のPHPコードを実行し、それを表示します(エコー)。私のクライアントサイドのC++コードでは、単純なHTTPリクエストを行います。私は問題がクライアント側ではなくサーバー側にあることを確認しました。winsockからすべてのバイトの応答が得られない

クライアント側のソケットコード:

locale local; 
char buffer[1000000]; 
int i = 0; 

string get_Website(string url, string path = "/", string useragent = "Mozilla") { 
    string website_HTML; 
    WSADATA wsaData; 
    SOCKET Socket; 
    SOCKADDR_IN SockAddr; 
    int lineCount = 0; 
    int rowCount = 0; 
    struct hostent *host; 
    string get_http; 


    get_http = "GET " + path + " HTTP/1.0\r\nHost: " + url + "\r\nUser-Agent: " + useragent + "\r\nConnection: close\r\n\r\n"; 

    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { 
     cout << "WSAStartup failed.\n"; 
     system("pause"); 
     //return 1;- 
    } 

    Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
    host = gethostbyname(url.c_str()); 

    SockAddr.sin_port = htons(44980); 
    SockAddr.sin_family = AF_INET; 
    SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr); 

    if (connect(Socket, (SOCKADDR*)(&SockAddr), sizeof(SockAddr)) != 0) { 
     cout << "Could not connect"; 
     system("pause"); 
     //return 1; 
    } 
    send(Socket, get_http.c_str(), strlen(get_http.c_str()), 0); 

    int nDataLength; 
    while ((nDataLength = recv(Socket, buffer, 1000000, 0)) > 0) { 
     int i = 0; 
     while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') { 

      website_HTML += buffer[i]; 
      i += 1; 
     } 
    } 

    closesocket(Socket); 
    WSACleanup(); 
    return website_HTML; 
} 

応答長は、私は毎回サーバ側と同じ応答を返すものの、変化し続け。大きなバッファの理由は、ファイルbase64でエンコードされたフォーム全体を取得しているので、それが問題になるかもしれないと思ったからです。

本質的に、問題は私が完全な/正しい応答を得ていないことです。

+1

受信したバイト数は 'recv()'から返され、 'nDataLength'に割り当てられます。次に、示されたコードは 'nDataLength'を完全に無視し、代わりに受信パケットの長さがどのように決定されるかを仮定して、' buffer'の最初の印字不可能な文字を探しています。それは明らかに間違っており、それはあなたのバグです。 –

+0

あなたの回答を回答として投稿してください。私は正しい印を付けることができます:)。前もって感謝します。 @SamVarshavchik –

+0

https://stackoverflow.com/questions/22077802/simple-c-example-of-doing-an-http-post-and-consuming-the-response/22135885#22135885のrecvループをご覧ください –

答えて

0
while ((nDataLength = recv(Socket, buffer, 1000000, 0)) > 0) { 

これはソケットから読み取ります。読み取られたバイト数は `nDataLength 'になります。その直後:

int i = 0; 
    while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') { 

     website_HTML += buffer[i]; 
     i += 1; 
    } 

このロジックは完全にnDataLengthでのバイト数を無視し、ただやみくもに改行やキャリッジリターンではありません最初の制御文字まで、連続して、バッファの内容を読み取ります。

HTTPリクエストに対する応答に確かにバイナリ文字が含まれていることに加えて、HTTPリクエストに対する応答は、サイズが異なる複数のパケットで到着し、連続して書かれます(buffer)。 。割り当てられたbufferは静的記憶域にあるように見えるため、ゼロ初期化が行われます。単一パケットが999999バイトを超えることはほとんどありません。したがって、ループがバッファの最後から実行されることはありません。ある時点で\0に当たるでしょう。

しかし、レスポンスのパケットはさまざまなサイズになるため、短いパケットの方が前のパケットの最初の長いコンテンツを置き換えます。破損したロジックはそれを検出することができず、新しいパケットの後に前のパケットの後端が続くことになります。

多少乱雑です。 nDataLengthを使用してそれを修正し、各パケットの内容をコピーして文字列に追加します。

関連する問題