6

何か問題があり、それはコードだと思います。

このアプリケーションは、一部のカスタムメイドのネットワーク デバイスに「ping」を実行して、それらが動作しているかどうかを確認するために使用されます。特別な UDP パケットを使用して 20 秒ごとに ping を実行し、応答を待ちます。3 回連続して ping に応答しない場合、アプリケーションはスタッフに警告メッセージを送信します。

アプリケーションは 24 時間年中無休で実行されており、1 日にランダムな回数 (主に 2 ~ 5 回)、アプリケーションが UDP パケットの受信に正確に 10 分間失敗した後、すべてが正常に戻ります。この 10 分間、応答しているように見えるデバイスは 1 つだけで、他のデバイスは停止しているように見えます。ログから推測できたこと。

Wireshark を使用してパケットを盗聴し、ping パケットが送信と受信の両方で送信されることを確認したので、ネットワーク部分は OS まで問題なく動作しているようです。コンピューターは WinXPPro を実行しており、ファイアウォールがまったく構成されていないコンピューターもあります。この問題は、さまざまなコンピューター、さまざまな Windows インストール、およびさまざまなネットワークで発生しています。

ここで何が問題なのか、私は本当に途方に暮れています。

すべてのネットワークを実行するコードの関連部分を添付します。これは、アプリケーションの残りの部分とは別のスレッドで実行されます。

あなたが提供するかもしれないどんな洞察にも、前もって感謝します。

def monitor(self):
    checkTimer = time()
    while self.running:
        read, write, error = select.select([self.commSocket],[self.commSocket],[],0)
        if self.commSocket in read:
            try:
                data, addr = self.commSocket.recvfrom(1024)
                self.processInput(data, addr)
            except:
                pass

        if time() - checkTimer > 20: # every 20 seconds
            checkTimer = time()
            if self.commSocket in write:
                for rtc in self.rtcList:
                    try:
                        addr = (rtc, 7) # port 7 is the echo port
                        self.commSocket.sendto('ping',addr)
                        if not self.rtcCheckins[rtc][0]: # if last check was a failure
                            self.rtcCheckins[rtc][1] += 1 # incr failure count
                        self.rtcCheckins[rtc][0] = False # setting last check to failure
                    except:
                        pass

        for rtc in self.rtcList:
            if self.rtcCheckins[rtc][1] > 2: # didn't answer for a whole minute
                self.rtcCheckins[rtc][1] = 0
                self.sendError(rtc)
4

2 に答える 2

3

select()あなたはそれについて言及していないので、そのソケットを使用しているので、ノンブロッキングの方がよいことを思い出してください。それ以外の場合は、recvfrom()ブロックできます。適切に対処すれば実際に発生することはありませんが、短いコード スニペットから判断するのは困難です。

次に、UDP ソケットの書き込み可能性をチェックする必要はありません。常に書き込み可能です。

本当の問題は、パケットがシステムに入っていると言っていますが、コードがそれらを受信して​​いないということです。これは、ソケット受信バッファのオーバーフローが原因である可能性が最も高いです。過去 15 年間で ping ターゲットの数は増加しましたか? あなたは ping 応答の嵐に備えて準備をしていて、おそらくそれらの応答を十分に速く読み取っていないため、受信バッファーに蓄積され、最終的にドロップされます。

ROIの順に私の提案:

  • ping 要求を分散させてください。DDOS を設定しないでください。たとえば、反復ごとに 1 つのシステムをクエリし、ターゲットごとに最後のチェック時間を保持します。これにより、出入りするパケットの数を均等にすることができます。
  • SO_RCVBUF大きな値に増加します。これにより、ネットワーク スタックがパケット バーストをより適切に処理できるようになります。
  • ループ内でパケットを読み取ります。つまり、UDP ソケットが読み取れるようになったら (非ブロッキングであると仮定して)、 が得られるまで読み取りますEWOULDBLOCKselect()これにより、一連の通話を節約できます。
  • Linux の行に沿って高度な Windows API を使用できるかどうかを確認してくださいrecvmmsg(2)。そのようなものが存在する場合は、syscall ごとに複数のパケットをデキューします。

お役に立てれば。

于 2012-07-18T12:32:48.010 に答える
0

UDP は信頼できる送信を保証しません。これは、今、次の 1 時間、次の年に機能する可能性があります。それから 2 年後には 1 時間通信できなくなります。

状況によっては、パケットのルート パスがブロックされることがあります。これが TCP で発生すると、送信者に損失が通知され、送信者は別のルート パスを介して送信を試みる場合があります。UDP は "send-and-forget" 送信プロトコルであるため、パケットの一部が統計的に失われる可能性があります。

tl;dr TCP を使用します。

于 2012-07-18T07:57:45.343 に答える