2

BSD ソケットを使用してサーバーから Web ページを取得し、それをファイルに書き込むコードがあります。以下は、すべてのファイル I/O とソケットでの書き込みと読み取りを処理するコードです。_sockfdはトーカーとリスナーの間の有効なソケットであることに注意してください。

    FILE* resultFile;
    resultFile = fopen(resultFilename.c_str(), "w+");

    if (resultFile != 0)
    {
        // Construct the request
        std::stringstream requestBuilder("");
        requestBuilder << "GET " << directory << " HTTP/1.1\r\nHOST:" << _hostname << "\r\n\r\n";

        std::string request = requestBuilder.str();

        // Prepare to read the file and write it out
        int bufferSize(1024);
        char buffer[bufferSize];
        int bytesRead(1);

        // Send request
        int bytesWritten = write(_sockfd, request.c_str(), request.length());
        if (bytesWritten < 0)
        {
            std::cout << "Error on initial request send" << std::endl;
            return false;
        }

        // Read response
        while (bytesRead > 0)
        {
            bzero(buffer, bufferSize);
            bytesRead = read(_sockfd, buffer, bufferSize);

            if (bytesRead < 0)
            {
                std::cout << "WebCrawler -> ERROR: Could not read properly from socket" << std::endl;
                return false;
            }

            fputs(buffer, resultFile);
        }

        fclose(resultFile);
        _socketUsed = true;

このコードが生成することを期待している結果は、次のスニペットのようになります。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>

<head>
<title>Serebii.net Pok&eacute;dex - #089 Muk</title>

<meta name="GENERATOR" content="Arachnophilia 4.0">
<meta name="FORMATTER" content="Arachnophilia 4.0">
<meta name="keywords" content="Pokemon, Pokédex, Muk (Pokémon),Muk, Diamond, Pearl, Platinum,     HeartGold, SoulSilver" />
<link rel="stylesheet" type="text/css" HREF="/style/dex.css">

</head>

<meta http-equiv="imagetoolbar" CONTENT="no">
    <link rel="stylesheet" type="text/css" HREF="http://www.serebii.net/spp-temp.css">
   <LINK REL="SHORTCUT ICON" HREF="http://www.serebii.net/favicon.ico">

<BODY  ondragstart="return false"  text=#000000 bottomMargin=0 bgcolor="#383838" 
leftMargin=0 topMargin=0 rightMargin=0>
    <table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse"     bordercolor="#111111" width="100%" height="1" background="http://www.serebii.net/BannerBg.jpg">
      <tr>

しかし、代わりに、次のようになります。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>

<head>
<title>Serebii.net Pok&eacute;dex - #089 Muk</title>

<meta name="GENERATOR" content="Arachnophilia 4.0">
<meta name="FORMATTER" content="Arachnophilia 4.0">
<meta name="keywords" content="Pokemon, PokÈdex, Muk (PokÈmon),Muk, Diamond, Pearl, Platinum,     HeartGold, SoulSilver" />
<link rel="stylesheet" type="text/css" HREF="/style/dex.css">

</head>


8c1
<meta http-equiv="imagetoolbar" CONTENT="no">
    <link rel="stylesheet" type="text/css" HREF="http://www.serebii.net/spp-temp.css">
   <LINK REL="SHORTCUT ICON" HREF="http://www.serebii.net/favicon.ico">

<BODY  ondragstart="return false"  text=#000000 bottomMargin=0 bgcolor="#383838" 
leftMargin=0 topMargin=0 rightMargin=0>
    <table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="100%" height="1" background="http://www.serebii.net/BannerBg.jpg">
      <tr>

ご覧のとおり、私のコードはどういうわけか奇妙な文字 (この場合は "8c1") を結果に挿入しています。これが HTML ドキュメント全体で何度も発生することを強調したいと思います。簡潔にするために、その例を 1 つだけに限定しました。どうにかしてバッファを誤用しているのではないかと思いますが、これまでのところ解決策を見つけることができませんでした.

私の問題を解決するための以前の取り組みには、次の SO の質問が含まれていました。

C Winsock プログラミング: 入力ガベージ

Raw Sockets : レシーバー印刷のガベージ値

また、次のページを参照して、C ファイル I/O を適切に行っていることを確認しました (C++ で fstream を使用することに慣れています)。

http://www.cprogramming.com/tutorial/cfileio.html

私はソケットを使用したネットワーク プログラミングに非常に不慣れです (おそらくおわかりのように)。私よりもはるかに経験豊富な人へ: 解決策を直接教えてもらえなくても、私がどこを間違えた可能性があるかについて、あなたの考えを教えてください。答えを見つけるために必要なのは、適切に配置されたいくつかのパンくずリストだけである場合があります。そのために、間違ったコードを表示している場合や、コードの別の部分がより役立つと思われる場合はお知らせください。

さらに、これは私の最初の SO の質問です。私の将来の質問がより良く、サイトにとってより適切であることを確認するために、あなたが適切だと思うようにそれを批評してください.

****更新 1**** (fputs を fwrite に変更するという Mark Ransom の提案の後):

に変更fputs(buffer, resultFile);しましたfwrite(buffer, 1, bytesRead, resultFile);。この状況で使用するのがより適切であることがわかりました。

しかし、私の問題は解決しません。実際、新しいコード(および私の古いコード)を5回連続して実行した後、元の質問で誤って「ガベージ」値と呼んだ誤った値が毎回まったく同じであることがわかりました。それらはまったくランダムではありません。問題をより適切に説明するために、質問のタイトルを変更しました。

bufferもう少し突っ込んだ後、読み取りがファイル書き込みと同じ結果を生成した後に、その出力をコンソールに追加したいと思います。

4

1 に答える 1

3

fputs(buffer, resultFile);書き込みがバッファの最後で停止しないため、バッファ オーバーランが発生しています。最初に見つかったゼロ文字で停止します。これは、バッファの最後を過ぎたメモリ内のランダムな場所にあります。fwrite代わりに使用してください。

于 2012-08-14T21:55:57.693 に答える