4

私の解析プログラムの1つで、次のことを行う必要があります(C、C++、VC++で):-

ソケットプログラミングで100台のマシン(透析機)を接続する必要があります。各マシンにリクエストを送信し、マシンからの応答とマシンから取得するデータを受信します。そのデータを解析し、値をファイルに書き込む必要があります。5秒ごとに各マシンにリクエストを送信する必要があります.

したがって、上記のタスクを達成するために、次のように実行することを考えています:-

データベースから各マシンのIPとポートを読み取り、各マシンに接続するスレッドを作成し、各スレッドでサブスレッド(子スレッド)が作成され、マシンからデータを送受信および解析します5 秒ごと (および txt ファイルに値を書き込みます)。私の解析機能は共通になります。

それは実行可能な解決策ですか?助けてください。事前にお願いします。

4

3 に答える 3

4

あなたの解決策は、1つの点を除いて合理的に聞こえます。各マシンに接続するスレッドを作成し、次に送信、受信、および解析を管理するサブスレッドを作成すると述べています。サブスレッドを作成する必要がある理由がわかりません。接続スレッドですべてを処理できるはずです。また、接続ごとに 1 つのスレッドではうまくスケーリングできない可能性があることも考慮してください。このアプリケーションが多数のマシンを処理する必要がある場合は、マシンごとにスレッドを使用することは避ける必要があります。

接続ごとに 1 つのスレッドを使用する代わりに、単純なスレッド プールを使用してこれを実現することもできますが、これではうまくスケーリングできません。5 秒ごとにワーカー キューに置かれるタスクを作成することを検討できます。スレッドのプールは、接続、読み取り、切断、解析、および処理を行います。これが TCP/IP であると仮定すると、HTTP と同様に、接続を開いたままにするのではなく、読み取りごとに接続/切断する必要があります。

これは、 vc ++ スレッド プール関連の質問です。そして、ここにいくつかの関連情報があります。

別の方法として、ソケット通信にlibeventを使用することもできます。解析に関しては、 Apache ThriftJSonなど、使用できる他のライブラリもあり、これらはすべてオープン ソースです。これらの解析ライブラリの欠点は、オプションではない透析マシンも変更する必要がある場合があることです。Thrift のようなものを使用できる場合は、1 つのライブラリからすべてを取得できます: ソケット通信と解析。

接続ごとに 1 つのスレッドの単純なケースのコードを次に示します。

class ThreadInfo
{
public:
  ThreadInfo(const string &ipAddress, uint16_t port) : ipAddress_(ipAddress), port_(port) {}
  string getIpAddress() {return ipAddress_;}
  uint16_t getPort() {return port_;}
  string getRecvBuffer() {return recvBuffer_;}

private:
  string ipAddress_;
  uint16_t port_;
  string recvBuffer_;
};

void *threadEntryPoint(void *userData)
{
  ThreadInfo *threadInfo = (ThreadInfo*) userData;

  // You need to decide if you want to keep the connection open while sleeping
  // or open and close it for each transaction. Change code here accordingly.
  // Create socket with threadInfo->getIpAddress() and threadInfo->getPort()

  // while(1)
  //   Send request to each machine
  //   Get response from each machine and store in threadInfo->getRecvBuffer()
  //       The buffer could also be a local var in this function, decide accordingly
  //   parse data accordingly
  //   sleep 5 seconds
}

uint16_t getPort(int machineNum) { return 3456; }
string getIpAddress(int machineNum) { return string("192.168.1.2"); }
int main(int argc, char **argv)
{
   // 3 items that we need, and that you will have to plugin accordingly:
   //   1) Num threads, assuming 100 for now
   //   2) IP address of each external machine, implement getIpAddress() accordingly
   //   3) port of each machine, implement getPort() accordingly

   int numThreads(100);
   list<pthread_t> threadIdList;

   for(int i = 0; i < numThreads; ++i)
   {
      pthread_t threadId;
      ThreadInfo *threadInfo = new ThreadInfo(getIpAddress(i), getPort(i));
      pthread_create(&threadId, NULL, threadEntryPoint, threadInfo);
      threadIdList.push_back(threadId);
   }

   // Wait for the threads to finish
   std::list<pthread_t>::iterator iter = threadIdList.begin();
   while(iter != threadIdList.end())
   {
     pthread_t threadId = *iter++;
     pthread_join(threadId, NULL);
   }
}
于 2012-09-18T07:15:48.913 に答える
1

100 台のマシンの場合、5 秒ごとにポーリングし、マシンごとに 1 つのスレッドが妥当です。スレッドは、ほとんどの場合、スリープ (5000) でブロックされ、ほとんどの場合、ソケット I/O またはディスク I/O でブロックされます。残りの時間。この種の読み込み (または 5 倍の読み込み) では、非同期 I/O またはスレッド プールに頼る必要はないと思います。

@Bradyが指摘したように、要件が投稿どおりであると仮定すると、接続ごとに複数のスレッドが必要になる理由がわかりません-5秒ごとにポーリングし、返信をテキストファイルに書き込むだけです。

私は、5 秒の間隔は安全上重要なリアルタイム要件ではなく、一時的なソフトウェアまたはネットワークの遅延のために期間が 6 秒になる場合でも、透析装置は正常に動作し続けると推測しています (期待しています:)。 . 私は血液学者/腎臓専門医ではありませんが、ポーリング/指示が1秒余分に遅れる場合があれば、透析装置が全体的な治療に大きな変化をもたらすことができれば(これには数時間かかります)、私は驚くでしょう.

編集 - 再。「関数の解析とファイル関数へのデータの書き込みは、すべてのスレッドに共通です」-マシンごとに異なるテキストファイルを想定すると、問題ないはずです。ログがすべて 1 つのログ ファイルに書き込まれる場合、それはさらに問題になります。各ログ エントリは、ログ ファイルに単独で書き込む 1 つのロガー スレッドのキューに入れられる必要があります。この種の機能を既にサポートしている実績のある既存のロガー フレームワークを使用するのが最も簡単なソリューションです。

于 2012-09-18T09:22:21.500 に答える
0

ネットワーク IO とディスク IO の両方にboost::asioフレームワークを使用すると、処理するスレッドがマシンごとに 1 つよりもはるかに少なくなる可能性があります。

さらに、ソケット プログラミング用の優れた高レベル インターフェイスを備えています。

于 2012-09-18T07:44:51.867 に答える