2

ロギング DatagramHandler の Python ドキュメントに示されているサンプル コードを取得する際に問題が発生しています。以下に示すコードでは、受信したすべてのデータグラムで EOFError 例外が発生します。

import socket
import logging
import cPickle
import struct
import sys

sock = socket.socket (socket.AF_INET, socket.SOCK_DGRAM)
sock.bind (('localhost', 9000))

handler = logging.StreamHandler()
handler.setFormatter(logging.Formatter("UDP LogViewer %(asctime)s %(message)s"))
logger = logging.getLogger("Test")
logger.addHandler(handler)

try:
    while True:
        dgram_size = sock.recv(4)
        if len(dgram_size) < 4:
            break
        slen = struct.unpack(">L", dgram_size)[0]
        data = sock.recv(slen)

        while len(data) < slen:
            data = data + sock.recv(slen - len(data))

        try:
            obj = cPickle.loads(data)
            record = logging.makeLogRecord(obj)
            logger.handle(record)
        except:
            print "exception", sys.exc_info()[0]



finally:
    sock.close()

ただし、このコードは機能しますが、アイデアはありません

data, address = sock.recvfrom(8192)
rec = logging.makeLogRecord(cPickle.loads(data[4:]))
logger.handle(rec)

よろしく

4

2 に答える 2

3

最初のrecv(4)呼び出しで、データグラムから最初の 4 バイトがコピーされ、残りのパケットがフロアにスローされると思います。2 回目の呼び出しではrecv、読み取るものが何も見つからず、EOFError が返されます。私のシステムのudp(7)マンページから:

   All receive operations return only one packet.  When the packet
   is smaller than the passed buffer, only that much data is
   returned; when it is bigger, the packet is truncated and the
   MSG_TRUNC flag is set.  MSG_WAITALL is not supported.

データグラム全体を読み取り、最初の 4 バイトから長さを取得してから、データグラム全体を格納する配列のサブセットを操作してみてください。

もちろん、ピクルスが接続のMTU内に完全に収まらない場合は、意図したとおりに機能しない可能性があります。

于 2010-12-09T11:52:20.153 に答える
0

完全な MWA は次のようになります。

最初の 4 バイト (pickle-data のサイズ) を破棄するだけであることに注意してください。これらは、TCP モードで動作するDatagramHandlerinheritsのために存在します。SocketHandlerただし、UDP を使用しているため、パケットの最後まで読み取ることができます。Sarnold が指摘しているように、データがパケットに収まらない場合は、より良い解決策が必要になります。UDP はパケットを見逃す可能性があるため、サーバー側のカスタマイズが必要になります。おそらく、最も単純なサーバー側の解決策は、そもそも制限を超えないようにメッセージを分割することです!

import socketserver
import socket
import pickle
import logging

class MyDatagramRequestHandler( socketserver.DatagramRequestHandler ):
    def handle( self ):
        try:
            while True:
                chunk = self.socket.recv( 2048 )
                chunk = chunk[4:]
                obj = self.unPickle( chunk )
                record = logging.makeLogRecord( obj )
                self.on_handle( record )
        except socket.timeout:
            pass

    def unPickle( self, data ):
        return pickle.loads( data )
        
    def on_handle( self, record: logging.LogRecord ):
        # do something, e.g.
        logger = logging.getLogger( record.name )
        logger.handle( record )

https://docs.python.org/3/howto/logging-cookbook.html#logging-cookbookの TCP の例から適応。

于 2020-09-16T11:14:23.747 に答える