2

UNIXソケットを使用してサーバーからhtmlファイルをダウンロードする簡単なプログラムを作成します。

write()を使用して "Get /index.html Host:* "メッセージを送信し、whileループを使用してread()応答を送信します。すべてうまくいきますが、0を返す最後のread()は、戻るのに長い時間がかかります。この特別な時間を待つ必要がないようにコードを修正するアイデアはありますか?またはこれはどのように起こりましたか?

    sprintf(cmdstr,"%s %s %s\r\nHOST:%s\r\n\r\n",METHOD,place,VERSION,host);
    cmdlen = strlen(cmdstr);
    if (write(sockfd,cmdstr,cmdlen) != cmdlen) {
       perror("write cmd error");
       return ;
    }

    while ((n = read(sockfd,read_data,BUFSIZE)) > 0) {
        read_data[n] = 0;
        p = read_data;

        if (filep == NULL) {
            if (filep = fopen(filename,"w")) == NULL) {
                perror("fopen ");
                return;
            }
            p = strstr(read_data,"\r\n\r\n");
            p += 4;
        }
        fputs(p,filep);
    }

    printf ("%s download completed.\n",filename);
4

2 に答える 2

1

BUFSIZE読み取る必要がなくなったときにデータを読み取るようにソケットに要求しているためです。readより多くのデータがTCP接続を通過するのを待っているブロックへの呼び出しは、接続がしばらくしてダウンしたときにのみ戻ると想定しています。

ファイルの大きさがわかっている場合は、その量のデータのみを読み取るように要求できます。ファイルの大きさがわからない場合は、ファイルが転送されたときに接続を閉じるためにサーバーに依存しています。

于 2012-04-05T08:46:03.153 に答える
1

準備ができているデータがない場合、recvブロックまたは失敗します(ブロックしているか非ブロックかによって異なります)。ソケットのもう一方の端が接続を閉じると、
recvゼロを返します。それ以外の場合はありません。

これは通常、HTTP / 1.1(現在のほとんどすべての既存のサーバー)では発生しません。接続はデフォルトで維持されると予想されるため、少なくともすぐには発生しません。

Connection: closeこの動作を望まないことをサーバーに通知するためにを送信します。その後、接続をできるだけ早くドロップする必要があります(ただし、もちろん、すべてを送信した後)。

shutdown(sockfd, SHUT_WR);または、接続の半分を実行し、サーバーが適切に反応する可能性のある(できれば)呼び出しを試すこともできます。

または、最後に、コンテンツの長さが示す範囲でしか読み取れず、接続を切断できますが、それはサーバーに対して一種の反社会的であり、完全にリスクがないわけではありません。

于 2012-04-05T09:16:30.247 に答える