7

これは観察であり、このシナリオを処理する最善の方法についての提案でもあります。

私は 2 つのスレッドを持っています。1 つはデータを送り込むだけで、もう 1 つはデータを受信し、別のソケットを送信する前に多くの作業を行います。両方のスレッドは、ドメイン ソケットを介して接続されます。ここで使用されるプロトコルは UDP です。TCP はストリーム ベースであるため、使用したくありませんでした。つまり、キューにほとんどスペースがない場合、データは分割されて送信されます。分割してはならないデータを送信しているため、これは悪いことです。したがって、DGRAM を使用しました。興味深いことに、送信スレッドが非常に多くのデータをポンピングして recv スレッドを圧倒すると、ある時点でドメイン ソケット バッファがいっぱいになり、sendto() が ENOBUFS を返します。これが発生した場合、sendto() はバッファーが使用可能になるまでブロックされるという意見でした。これは私の望ましい動作です。しかし、そうではないようです。私はこの問題をかなり奇妙な方法で解決します。

  • CPU Yield メソッド ENOBUFS を取得したら、sched_yield(); を実行します。OSX には pthread_yield() がないためです。その後、再送を試みます。それが失敗した場合、私はそれが取られるまで同じことを続けます. 役に立たないことをしているだけでCPUサイクルを浪費しているので、これは悪いことです。sendto() がブロックされれば幸いです。

  • スリープメソッド sched_yield() の代わりに sleep(1) を使用して同じ問題を解決しようとしましたが、sleep() は送信スレッドだけでなくプロセスをスリープ状態にするため、これは役に立ちません。

どちらも私にはうまくいかないようで、オプションが不足しています。誰かがこの問題を処理する最善の方法を提案できますか? 不要な CPU サイクルを減らすことができる、私が気付いていない巧妙なトリックはありますか? ところで、man ページがsendto () について述べていることは、この議論に基づいて間違っています

カーネルの Upd コード:

The udp_output function in /sys/netinet/udp_usrreq.c, seems clear:

         /*
          * Calculate data length and get a mbuf
          * for UDP and IP headers.
          */
         M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
         if (m == 0) {
                 error = ENOBUFS;
                 if (addr)
                         splx(s);
                 goto release;
         }
4

2 に答える 2

1

sendto() がブロックされない理由はわかりませんが、sendto() を呼び出す前に、この関数を呼び出してみてください。

#include <stdio.h>
#include <sys/select.h>

// Won't return until there is space available on the socket for writing
void WaitUntilSocketIsReadyForWrite(int socketFD)
{
   fd_set writeSet;
   FD_ZERO(&writeSet);
   FD_SET(socketFD, &writeSet);
   if (select(socketFD+1, NULL, &writeSet, NULL, NULL) < 0) perror("select");
}

ところで、送信しようとしているパケットの大きさはどれくらいですか?

于 2013-05-15T03:40:19.857 に答える
0

OS X の sendto() は実際にはノンブロッキングです (つまり、M_DONTWAIT フラグです)。

ストリームベースの接続を使用し、関数の MSG_WAITALL フラグを使用して反対側でデータ全体を受信することをお勧めしますrecv。データが単純な構造よりも厳密な構造を持っている場合は、正しいサイズをrecv. そうでない場合は、最初にデータの次のチャンクのサイズを含む固定サイズの制御パケットを送信し、次にデータ自体を送信します。受信側では、一定サイズの制御パケットと、制御パケットからのサイズのデータ​​を待ちます。

于 2013-05-15T09:40:52.550 に答える