2015-12-13 59 views
10

私はPythonのsocket.send()とsocket.sendall()関数についてちょっと混乱します。 the documentationからわかるように、send()関数はTCPルールを適用し、sendall()関数はデータをソケットに送信するためのUDPルールを適用します。また、どのパケットが送信され、どのパケットが送信されていないかを確認できるため、TCPはWebアプリケーションのほうが信頼性が高いことがわかります。だから、私はsend()関数を使うのではなくsendall()関数よりももっと信頼できると思うのですが、わかりません。この時点で、私はこれらの2つの機能の正確な違いは何か、Webアプリケーションの信頼性はどれですか?socket.send()とsocket.sendall()の違いは何ですか?

ありがとうございます。

+1

IMO - '.send()'はすべてのデータを送信するのではなく、 'sendall()'はすべてのデータが送信されるまで返るわけではありません。一般に、あなたが '.send()'を使う必要があることを知らない限り、 'sendall()'を使うべきです。 –

答えて

19

socket.sendは、低レベルの方法であり、基本的にはC/Syscallメソッドsend(3)/send(2)だけです。リクエストされたバイト数より少ないバイト数で送信できますが、送信バイト数が返されます。

socket.sendallは、渡すバッファ全体を送信する、または例外をスローする、高度なPython専用のメソッドです。すべてが送信されるか、エラーが発生するまで、socket.sendを呼び出すことによってそれが実行されます。

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

とPythonドキュメント:

送信()とは異なり、この方法は、全てのデータが送信されたかエラーが発生したいずれか まで文字列からデータを送信し続けます。 には何も返されません。エラーの場合は、例外が発生し、どのくらいのデータを決定 する方法はありませんが、もしあれば、成功した私は、過去に得た簡潔な説明のためにフィリップHagemeisterに

クレジットを送りました。フードsend

編集

sendall使用 - 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 source)から:

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() 
+0

ありがとうございます。私はポイントを持っています。 – cengineer

-7

すでに言及したドキュメントが言うように、センド()のためでありますTCPおよびsendall()UDPです。

これら二つの機能の違いを理解するためには、あなただけのTCPUDPの違いを知っている必要があります。つまり、send()は、ターゲット(サーバー)に送信されたバイト数を追跡​​し、その命令はすべてのbuffer_sizeがサーバーに受信されたときにのみ成功し、クライアントはサーバーに接続する必要があります。サーバは、ACKに関する情報を有する。 sendall()の場合

BUFFER = "a string" 
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
sock.connect((target_host, target_port)) 
client.send(BUFFER) 

、それだけでこのバッファが本当にサーバかにより受信されたか否かの情報を有することなく、ターゲット(サーバ)にバッファを送信します。

BUFFER = "a string" 
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
sock.connect((target_host, target_port)) 
client.sendall(BUFFER, (target_host, target_port)) 

希望に応えたい!

+0

この説明は非常に便利でした。ありがとうございました。私はTCPとUDPを知っていましたが、send()とsendall()について混乱しました。ポイントありがとう! – cengineer

+0

それを聞いてうれしい@MehmetAKALIN 8-) – MrHanachoo

+2

これは実際には真実ではありません。 TCP vs UDPではなくvs sendallを送信します。さらに、 'send'はバッファが送られることを保証しません、'返されたバイト数を返します。アプリケーションは、すべてのデータが送信されたことを確認する責任があります。データの一部だけが送信された場合、アプリケーションは残りのデータの配信を試みる必要があります。 – kwarunek

関連する問題