私は次のようにBerkeleyソケットのselect関数を利用しています。バークレーソケットでのスレッド通知の使用
/*Windows and linux typedefs/aliases/includes are made here with wsa
junk already taken care of.*/
/**Check if a socket can receive data without waiting.
\param socket The os level socket to check.
\param to The timeout value. A nullptr value will block forever, and zero
for each member of the value will cause it to return immediately.
\return True if recv can be called on the socket without blocking.*/
bool CanReceive(OSSocket& socket,
const timeval * to)
{
fd_set set = {};
FD_SET(socket, &set);
timeval* toCopy = nullptr;
if (to)
{
toCopy = new timeval;
*toCopy = *to;
}
int error = select((int)socket, &set, 0, 0, toCopy);
delete toCopy;
if (error == -1)
throw Err(); //will auto set from errno.
else if (error == 0)
return false;
else
return true;
}
私は(aotherクラスに包ま)ソケットのコンテナを見て、ソケットにアクセスする準備ができているかについての情報を保存する別の容器にIDを追加するクラスを書かれています。マップはunordered_mapです。
while(m_running)
{
for(auto& e : m_idMap)
{
auto id = e.first;
auto socket = e.second;
timeval timeout = ZeroTime; /*0sec, 0micro*/
if(CanReceive(socket,&timeout) &&
std::count(m_readyList.begin(),m_readyList.end(),socket) == 0)
{
/*only add sockets that are not on the list already.*/
m_readyList.push_back(id);
}
}
}
私は多くの人が気づいていると確信しているように、このコードはめちゃくちゃ速く走ると明日(マップ内の1つのソケットだけで40%のCPU使用率)がないようにCPUをアップゴブルズ。私の最初の解決策は、毎秒の繰り返しを設定値に保つスマートな待機関数を用意することでした。それはいくつかの人々とうまくいくようでした。 私の質問はこれです:このメソッドを使わずにソケットが準備できたら、どうすれば通知することができますか?たとえそれが移植性を保つためにマクロジャンクを必要としても大丈夫です。私は、オペレーティングシステムが私のためにそれを見て、ソケットが準備が整ったときにある種の通知やイベントを受け取れるようにする方法があるかもしれないと思うだけです。ちょうど明確にするために、私はドットネットを使用しないことを選択しました。
ループは独自のスレッドで実行され、ソケットの準備ができたらソフトウェアの他の部分に通知を送信します。全体がマルチスレッドであり、この部分を除くすべての部分でイベントベースの通知システムが使用され、ビジー状態の待機中の問題が解消されます。私は事がOSに依存し、この分野では限られていることを理解しています。
編集:ソケットはBLOCKINGモードで実行されます(ただし、選択にはタイムアウトがないため、ブロックされません)が、専用のスレッドで操作されます。 編集:システムはスマートスリープ機能を搭載していますが、いくつかの通知システム(OSからの可能性があります)と比べて優れた性能を発揮します。
なぜ 'recv'を呼び出さないのですか? 'recv'が何をするのかを予測しようとする' select'の余分な呼び出しの目的は何ですか? 'recv'を呼び出すだけで、何が起こるのか見てみませんか? –
また、これを行うにはライブラリを使用するだけです。それを100%正しくすることは仕事の大事なことです。あなたが発見したように、最小限のコードでそれを偽造するのは苦しいです。 ASIOには魅力的なものがあります。 –
David Schwartz:ソケットがすぐに私に何かを与えることがない場合、私は別のソケットに移動し、私に何かがあるかどうかを確認します。何千ものソケットがあります。 recvを呼び出すだけで1つのソケットをブロックすると、今すぐ準備ができている可能性のある他のソケットは無視されます。 no-blockオプションを指定してrecvを呼び出すと、まだ待っているので何も解決しません。 – Matt