6

Pythonネットワークプログラミングの学習を始めたばかりです。Foundations of Python Network Programming を読んでいましたが、s.shutdown(socket.SHUT_WR) の使用を理解できませんでした。ここで、s はソケット オブジェクトです。これが使用されるコード (ここで、sys.argv[2] はユーザーが送信したいバイト数で、16 の倍数に丸められます) です:

import socket, sys
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

HOST = '127.0.0.1'
PORT = 1060

if sys.argv[1:] == ['server']:
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind((HOST, PORT))
    s.listen(1)
    while True:
        print 'Listening at', s.getsockname()
        sc, sockname = s.accept()
        print 'Processing up to 1024 bytes at a time from', sockname
        n = 0
        while True:
            message = sc.recv(1024)
            if not message:
                break
            sc.sendall(message.upper())  # send it back uppercase
            n += len(message)
            print '\r%d bytes processed so far' % (n,),
            sys.stdout.flush()
        print
        sc.close()
        print 'Completed processing'

elif len(sys.argv) == 3 and sys.argv[1] == 'client' and sys.argv[2].isdigit():

    bytes = (int(sys.argv[2]) + 15) // 16 * 16  # round up to // 16
    message = 'capitalize this!'  # 16-byte message to repeat over and over

    print 'Sending', bytes, 'bytes of data, in chunks of 16 bytes'
    s.connect((HOST, PORT))

    sent = 0
    while sent < bytes:
        s.sendall(message)
        sent += len(message)
        print '\r%d bytes sent' % (sent,),
        sys.stdout.flush()

    print
    s.shutdown(socket.SHUT_WR)

    print 'Receiving all the data the server sends back'

    received = 0
    while True:
        data = s.recv(42)
        if not received:
            print 'The first data received says', repr(data)
        received += len(data)
        if not data:
            break
        print '\r%d bytes received' % (received,),

    s.close()

else:
    print >>sys.stderr, 'usage: tcp_deadlock.py server | client <bytes>'

そして、これは著者が提供する説明であり、私が理解するのが難しいと感じています:

2 番目に、クライアントが送信の送信を終了した後、ソケットで shutdown() 呼び出しを行うことがわかります。これにより、重要な問題が解決されます。サーバーがファイルの終わりを確認するまで永遠に読み取りを行う場合、クライアントはソケットで完全な close() を実行する必要がなくなり、多くの recv( ) サーバーの応答を受信するためにまだ行う必要がある呼び出しはありますか? 解決策は、ソケットを「半分閉じる」ことです。つまり、一方向の通信を永久にシャットダウンしますが、ソケット自体を破壊することはありません。これにより、サーバーはデータを読み取ることができなくなりますが、残りの応答を送り返すことができます。まだ開いている他の方向。

それが何をするかについての私の理解は、それがクライアントアプリケーションがそれ以上データを送信するのを防ぎ、したがってサーバー側がそれ以上データを読み取ろうとするのを防ぐことです。

私が理解できないのは、なぜこのプログラムで使用されているのか、どのような状況で自分のプログラムで使用することを検討すべきなのかということです.

4

2 に答える 2

4

それが何をするかについての私の理解は、それがクライアントアプリケーションがそれ以上データを送信するのを防ぎ、したがってサーバー側がそれ以上データを読み取ろうとするのを防ぐということです。

あなたの理解は正しいです。

私が理解できないのは、なぜこのプログラムで使用されているのかということです...</p>

あなた自身の声明が示唆するように、クライアントがなければs.shutdown(socket.SHUT_WR)、サーバーはデータの待機を中止せず、サーバーにsc.recv(1024)接続終了要求が送信されないため、永久に固執します。
サーバーはその に到達しないため、サーバーから接続終了要求が送信されないためsc.close()、クライアントもデータの待機を終了せず、永遠にそのままになります。「ソケットを閉じるかシャットダウンするか」に対するこの回答を 読んでください。啓発的でもあります。s.recv(42)

于 2016-04-04T08:24:08.593 に答える
-1

説明は中途半端で、この特定のコードにのみ適用されます。全体として、これは悪い習慣であると私は四つんばいで投票します。

その理由を理解するには、サーバー コードを確認する必要があります。このサーバーは、1024 バイトを受信するまで実行をブロックすることで機能します。受信すると、データを処理 (大文字に変換) して送り返します。問題はハードコードされた 1024 の値にあります。文字列が 1024 バイトより短い場合はどうなるでしょうか。

これを解決するには、サーバーに次のことを伝える必要があります。これ以上データが来ないので、元に戻っmessage = sc.recv(1024)て、ソケットを一方向にシャットダウンすることでこれを行います。

サーバーが応答を送信できなくなるため、ソケットを完全に閉じたくありません。

于 2016-01-31T16:37:43.593 に答える