GNU/Linux >> Linux の 問題 >  >> Linux

C/C++ (GCC/G++) を使用した Linux でのソケット プログラミングでのファイルの送受信

man 2 sendfile を実行 .クライアントでソース ファイルを開き、サーバーで宛先ファイルを開くだけで、sendfile を呼び出すと、カーネルがデータを切り刻んで移動します。


最も移植性の高い解決策は、ファイルをチャンクで読み取り、データをループでソケットに書き込むことです (同様に、ファイルを受信するときはその逆です)。 read というバッファを割り当てます そのバッファに入れ、write そのバッファからソケットに ( send を使用することもできます と recv 、データの書き込みと読み取りのソケット固有の方法です)。アウトラインは次のようになります:

while (1) {
    // Read data into buffer.  We may not have enough to fill up buffer, so we
    // store how many bytes were actually read in bytes_read.
    int bytes_read = read(input_file, buffer, sizeof(buffer));
    if (bytes_read == 0) // We're done reading from the file
        break;
    
    if (bytes_read < 0) {
        // handle errors
    }
    
    // You need a loop for the write, because not all of the data may be written
    // in one call; write will return how many bytes were written. p keeps
    // track of where in the buffer we are, while we decrement bytes_read
    // to keep track of how many bytes are left to write.
    void *p = buffer;
    while (bytes_read > 0) {
        int bytes_written = write(output_socket, p, bytes_read);
        if (bytes_written <= 0) {
            // handle errors
        }
        bytes_read -= bytes_written;
        p += bytes_written;
    }
}

read のドキュメントを必ずお読みください そして write 特にエラーを処理するときは慎重に。一部のエラー コードは、たとえば continue でもう一度ループするなど、もう一度やり直してください。 他のステートメントは、何かが壊れているので停止する必要があることを意味します。

ファイルをソケットに送信するために、システム コール sendfile があります。 それはあなたが望むことだけを行います。あるファイル記述子から別のファイル記述子にファイルを送信するようにカーネルに指示すると、カーネルは残りを処理できます。ソース ファイル記述子が mmap をサポートする必要があるという注意事項があります。 (ソケットではなく実際のファイルである場合のように)、宛先はソケットでなければなりません (そのため、ソケットを使用してファイルをコピーしたり、あるソケットから別のソケットにデータを直接送信したりすることはできません)。ファイルをソケットに送信するという、説明した使用法をサポートするように設計されています。ただし、ファイルの受信には役立ちません。そのためには、自分でループを実行する必要があります。 sendfile がある理由はわかりません 呼び出しますが、類似の recvfile はありません .

sendfile に注意してください Linux 固有です。他のシステムには移植できません。他のシステムには独自のバージョンの sendfile があることがよくあります ですが、正確なインターフェースは異なる場合があります (FreeBSD、Mac OS X、Solaris)。

Linux 2.6.17 では、splice システムコールが導入され、2.6.23 の時点で sendfile を実装するために内部で使用されています . splice sendfile よりも汎用的な API です。 . splice の適切な説明 と tee 、Linus 自身によるかなり適切な説明を参照してください。彼は splice の使い方を指摘しています read を使用して、基本的に上記のループと同じです。 そして write ただし、バッファーはカーネル内にあるため、カーネルとユーザー空間の間でデータを転送する必要がなく、CPU を通過することさえありません (「ゼロコピー I/O」と呼ばれます)。


Linux
  1. Linuxで検索および検索コマンドを使用してファイルを検索する

  2. Howto:Linux での一時ファイルを使用した C プログラミング

  3. (C/C++) Windows と Linux の両方で実行できる実行可能ファイルを生成する方法は?

  1. findコマンドを使用してLinux上のファイルとディレクトリを検索します

  2. xclipを使用してLinuxコマンドラインでコピーして貼り付けます

  3. Linuxリアルタイムシナリオとそのソリューションの問題

  1. Linuxでの入出力とエラーリダイレクトの操作

  2. Linuxでのファイルパーミッションと例

  3. Linux から添付ファイルと本文を含むメールを送信する方法