2012-01-19 15 views
0

私はファイルのパラレルダウンロードを取得したいと思います。例えば、54kbのファイルサイズであれば、10kbのブロックにファイルの内容をダウンロードしたいと思います。どのようにして並列的にダウンロードするコードを書くことができますか?

さらに、一度に5件を超えるリクエストはありません。 ですがどうですか?私はfork()を使うことを考えましたが、実際にどのように理解していません。

1-10最初の要求
11-20第2の要求
21-30第三の要求
31-40第四の要求
41-50第要求


51-54待機過去まで1つのリクエストが終了します。それが実行されます。

私はデータを取得する方法(recvなど)は気にしません。私はちょうど同時メソッドを実装する方法を知りたいですか? (私がfork()でできるならばより良い)

+1

代わりにスレッド上でチュートリアルを探し始めることをお勧めします。ダウンロードが1つのプロセスですべて完了した場合、ダウンロードを同期する方が簡単かもしれません。それ以外の場合は、共有メモリや共有ファイル、ファイルロックに関するチュートリアルを参照してください。 –

+0

子供にスレッドを使用することは可能ですか? – rschirin

+0

一般に、子プロセスとスレッドは混在させずに、どちらか一方を使用します。複数のスレッドはすべて、それらを作成したプロセスのリソースを共有しますが、別のプロセスは何も共有しません。 –

答えて

0

この機能を提供するいくつかの容易に利用可能なソフトウェアライブラリがあります。私が考えることができる主なものはカールです。 カールマルチライブラリhereへの簡単な紹介を見つけることができます。

非常に良い理由(技術の向上や学術研究の改善など)がない限り、ホイールの再発明は避けるのが最善です。

学術研究のため、また「リンク専用」の回答で十分ではないので、私はマルチプレクサソケットに関する多くの可能な方法の1つについて詳しく説明します。


ノンブロッキングソケット

まず、現在はほとんどのポータブル方法は、非ブロッキングソケットおよび/または非ブロックソケット呼び出しを使用することで、しかし、使用して(場合は特に認識することが重要ですノンブロッキングソケットは、O_NONBLOCKをファイル記述子に設定するのではなく、を呼び出します。一部のものはまだブロックされます。たとえば、ファイル記述子を非ブロックモードに設定し、もちろんgetaddrinfo(同様の標準的な名前解決関数)もブロックしない限り、connectをすぐに返すことはできません。

非ブロッキングファイルや関数呼び出しを使用すると、関数はすぐに戻ります。データが準備されていない場合、戻り値によってこれが示されます。処理できるデータがある場合は、再び戻り値が表示されます。

ノンブロッキングソケットコール(connectを含む)を確実にする方法は2つあります。

  1. UNIXシステムの場合は、fcntl(socket_fd, fcntl(socket_fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK)を呼び出します。その後、readwriteacceptconnectへのすべてのコールは、すぐに返されます。には、EALREADY,EINPROGRESSEISCONNEWOULDBLOCKのようないくつかのエラーコードがあります(ノンブロッキングを有効にすると、は実際には成功戻り値です)。変装で; errnoをチェックする必要があります。
  2. Windowsシステムの場合は、ioctlsocket(socket_fd, FIONBIO, (u_long[]){1})を呼び出します。 errnoコードがerrnoコード(代わりにGetLastError()コードになる)を除いて、同じセマンティクスが上記のように発生します...おそらく異なる値ですが、わかりません。私は、

    #ifdef _WIN32 
    #define set_nonblock(fd) (ioctlsocket(fd, FIONBIO, (u_long[]){1}) == 0) 
    #define EAGAIN   WSAEWOULDBLOCK 
    #define EWOULDBLOCK  WSAEWOULDBLOCK 
    #define EISCONN   WSAEISCONN 
    #define EINPROGRESS  WSAEINPROGRESS 
    #define EINVAL   WSAEINVAL 
    #define EALREADY   WSAEALREADY 
    #else 
    #define set_nonblock(fd) (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK) != -1) 
    #endif 
    

だけではない、非ブロッキングソケットを使用して

言及に値する:私のプロジェクトで、私は通常のようなものを使用して、しかし、似た名前を持つ彼らの多くわずかな調整だけで、さまざまなシステム上で、1つのスレッドで数千の接続を維持することができれば、全く驚くことはありません。しかし、各ソケットを循環するためにビジーループが必要なので、このモデルは理想的ではありません。ループごとにイベントを瞬時にテストします。たとえば、イベントが到着したときにOSによって起動するようにコードがトリガされるのではなく、

イベントをアプリケーションに送信するには、カーネルがイベントを処理する必要があるので、たとえばsleep(0);をクイックフィックスとして使用してください。これにより、CPU使用率が100%近くから10%に低下することが確認されます。しかしながら、機能がとなるように、ブロックされていない(またはタイムアウト中断された)機能を持つ多数の(ブロッキングまたは非ブロッキング)ソケットを多重化する別の方法があります。は、データを受信する。

selectが明らかに強力な利点を有するが、欠点もある。つまり、セットは通常、ソケットの数が少ないことに制限されています。多数のソケットをサポートするには、64ソケット制限(またはそれが何であれ)がすぐに使い果たされるので、ループ内にループが必要です。さらに、は、connectブロック問題を解決しません(ここでは、O_NONBLOCKと〜FIONBIOメソッドがします)。

このように、私はselectについてこれ以上話しません。 他のオプションについてご説明します。同様の制限を伴う別の例は、pollです。私はそれについても話しません。あなたはそれについて知りたい場合は、それについては、インターネット上でたくさん...あなたが共通にそれらのすべてをラップする方法を見つけるかもしれませんがこの時点からすべてが(かなり非ポータブルであること


注意がありますインターフェイス、カールマルチのように)。


非同期ソケットは、接続を開始し、彼らはまた、信号を上げたり、接続が完了したときに指定した関数を呼び出しますを除いて、その後、非ブロックソケット呼び出しのようにすぐに戻りますを呼び出します。これは、OSがあなたを待っているのではなく、イベントが到着したときにあなたのコードに通知するようにOSを制御しています。最適化が進む限り、非同期ソケットは理想的ですが、は移植性がありません。 OSごとにさまざまなオプションがあります:FreeBSD用のLinux

  • kqueueため

    これらのすべてに共通点があります。これは、成功または失敗時に関数を呼び出す(または関数の呼び出しに変換できるシグナルを発生させる)ことです。しかし、そのインタフェースはあまりよく知られているものではありません。

    通常、私はこの回答の冒頭で述べたノンブロッキングソケットが今日よりはるかに適切であることを知っているので、それらのラッパーを作成するのは面倒ではありません。重要なのは、私はそれをすべてのシステムに移植する必要はないということです。なぜなら、私はあまりにも怠け者だからです!誰かがそのシステムで遅いことを私に示すとき、私はシステムに対してのみ最適化します。さもなければ、私たちは、人々が私たちのソフトウェアを使用していないかもしれないシステムの急流に自分自身を掘り下げてしまう...

  • 関連する問題