1. ホーム
  2. python

socket.send()とsocket.sendall()の違いは何ですか?

2023-10-19 08:49:56

質問

について混乱しています。 socket.send()socket.sendall() という関数をPythonで使うことができます。私が理解するところでは のドキュメントでは send() 関数は TCP プロトコルを使用し sendall() 関数はデータの送信に UDP プロトコルを使用します。どのパケットが送信され、どのパケットが送信されなかったかを確認できるため、ほとんどのWebアプリケーションではTCPの方が信頼性が高いことが分かっています。そのため、私は send() 関数を使う方が sendall() 関数よりも信頼できます。

この時点で、この2つの関数の正確な違いは何か、Webアプリケーションではどちらがより信頼できるのか、と問いたいのです。

ありがとうございます。

どのように解決するのですか?

ソケット送信 は低レベルのメソッドで、基本的にはC/syscallのメソッドだけです。 send(3) / 送信(2) . 要求したバイト数よりも少ないバイト数を送ることができますが、送ったバイト数を返します。

socket.sendall は、渡されたバッファ全体を送信するか、例外を投げる、高レベルのPython専用メソッドです。これは socket.send を呼び出すことで行います。

ブロッキングソケットでTCPを使用していて、内部処理に煩わされたくない場合(ほとんどの単純なネットワークアプリケーションがそうです。 内部で煩わされたくない場合(これはほとんどの単純なネットワークアプリケーションの場合です)。 sendallを使用します。

そしてpythonのdocs。

send()とは異なり、このメソッドは文字列からデータを送信し続けます。 すべてのデータが送信されるか、エラーが発生するまで、このメソッドは文字列からデータを送信し続けます。成功した場合は、何も返されません。 成功した場合は何も返されません。エラーの場合は、例外が発生し を判断する方法はありません。 どの程度のデータ を判断する方法がありません。

フィリップ・ハーゲマイスター(Philipp Hagemeister)に、私が過去に得た簡単な説明を謝辞として述べています。

編集

sendall 裏技を使う send - を見てみる cpython の実装を見てください。以下は、(多かれ少なかれ)次のように動作するサンプル関数です。 sendall :

def sendall(sock, data, flags=0):
    ret = sock.send(data, flags)
    if ret > 0:
        return sendall(sock, data[ret:], flags)
    else:
        return None

または rpython (pypyのソース) :

def sendall(self, data, flags=0, signal_checker=None):
    """Send a data string to the socket.  For the optional flags
    argument, see the Unix manual.  This calls send() repeatedly
    until all data is sent.  If an error occurs, it's impossible
    to tell how much data has been sent."""
    with rffi.scoped_nonmovingbuffer(data) as dataptr:
        remaining = len(data)
        p = dataptr
        while remaining > 0:
            try:
                res = self.send_raw(p, remaining, flags)
                p = rffi.ptradd(p, res)
                remaining -= res
            except CSocketError, e:
                if e.errno != _c.EINTR:
                    raise
            if signal_checker is not None:
                signal_checker()