ソケットソケットとスティックパッケージの問題

A、Scoketソケット

ベースのscoket TCPプロトコル    TCPはリンクに基づいており、最初にサーバを起動し、サーバーのリンクにクライアントを起動する必要があります

シンプルなバージョンをscoket    送信し、recvの相補的である、それはペアリングする必要があります。recvのは、あなたが考慮する必要があるデータソースとして、データをメモリです。

送信およびRECV注:RECVのみ(******)のデータサイズを受信する番号を記入することができ、データにのみ、バイナリデータを送信する送信

TCPは、意志の特徴データと相手に送信比較的短時間のデータパッケージよりも小さな時間間隔

エンドサーバー

輸入ソケット

サーバー = socket.socket()  サーバー側でオブジェクトを作成 
server.bind((' 127.0.0.1 '、8080))  バインド((ホスト、ポート))#IPおよびポートバインディング 
server.listen(5)セミ結合をプールは、クライアントに接続されたユーザの数を制限 
CONNを、ADDR = server.accept()  のconnはaddrがクライアントのアドレスであるデータ伝送チャネルに対して(双方向チャネル)を待っている 
データ= conn.recv(1024) RECVクライアントを介して送信されるデータを受信します、唯一のrecvデジタルが埋めることに注意して印刷(データ) 


conn.send(B ハローベイビー〜#sendクライアントに情報を送信、バイナリデータ
 
はconn.close() は通路閉鎖 
server.closeを() 閉じるサーバー

クライアント側

輸入ソケット

クライアント = socket.socket() クライアントオブジェクトを作成 
client.connect((' 127.0.0.1 '、8080))サーバー接続とポートの#のIP 
client.send(B ' のHello Worldが!'サーバーに送信#sendメッセージ、バイナリデータ 
データ= client.recv(1024)  サービス終了メッセージを受信#recv、RECVのみデジタル受信し、この図は、受信したデータサイズを表しプリント(データ)  
 


client.close() は、クライアントを閉じます

第二に、問題解決の通信サイクル

サーバーは、これらの2点を満たす必要があります。

  1. IPとポートを固定しています

  2.24時間ノンストップサービス

情報ソケットは、トップの簡易版を送り、それは固定IPとポートを満たすためにではあるが、限られているが、それはアクセスすることは必ずしも可能ではないので、クライアントとサーバは、それぞれのサイクルを書き込み、クライアントが入力し続け常にプリントサーバーを受け取ります。

サーバー側の   内部ループは、連続してデータ転送を介してクライアントから受信されたクライアントの切断は、その後、休憩、ConnectionRestErrorを投げた場合に決定されます

インポートソケット
 
サーバー = socket.socket()  、オブジェクトを生成 
server.bind((' 127.0.0.1 '、8080))  バインディングIPとポート 
server.listen(5)  セミ結合プールを

しばらく真:
    CONNは、ADDR = server.accept()   #1 CONNに他の誰かのための待ち時間は、双方向チャネルはに似ている
    しばらく:真の
         試み
            データ = conn.recv(1024 印刷(データ)   #のB '' 
            IF LEN(データ)== 0:BREAKの  サーバがエラーなしB受信のみしている異常終了した後、MacとLinuxクライアントのための'' どのステップは書くことができません
             (data.upper())conn.sendを
         除い:E AS ConnectionResetError    クライアントは、例外エラー出口受信
            印刷(E)
             BREAK 
    はconn.closeを()

クライアント側

輸入ソケット

クライアント = socket.socket()
client.connect((' 127.0.0.1 '、8080 ))   接続サーバー

しばらく真:
    MSG = INPUT(' >>>:').encode(' UTF-8。' #クライアント入力
    のIF lenは(MSG)== 0:続行を    もう一度入力引き続き、入力が空の場合、#が決定 
    client.send(MSGを)   #サーバにデータを送信し、バイナリ形式でMSGデータがなければならない 
    データ = client.recv(1024 )#側サービスデータ受信送信
    印刷)データ(

三、TCPパケット粘着性の問題

スティックパッケージが発生:送信側の結果の別の部分は、送信コマンド(データ過負荷)を行い、得られた結果は、受信機はそれらが受信次回の前に行う実行中のコマンドを受信し、の一部であってもよいあり、これは明らかスティックパッケージであります。

二つの公式の説明は、スティック包装に行われます。

送信側は、スティックパッケージをもたらす、バッファが送出さ一杯になるまで待機する必要がある(データ送信時間間隔が短い、データがスティックパッケージを生成するために一緒に参加すること、小さい)場合

ケース2:受信者は、パケットバッファがタイムリーではない受け取り、複数のパケットが得られ、サーバが収集時にバッファから取得するための次または最後のサーバーのほんの一部分を受け、(クライアントから送信されたデータの一部を受け取りますレガシーデータ生成スティックパッケージ)

概要:スティックパッケージは今だけTCPプロトコルを発生します。

図1は、表面に、粘着の問題は、送信者と受信者のためのTCPストリーム指向の通信プロトコル特有のパケット・キャッシング機構です。

図2に示すように、実際には、受信機はメッセージ間の限界を認識していない主な理由は、タイム抽出によるデータのバイト数を知りません。

スティックのパッケージ・ソリューション:

受信側、その後、問題の根は、受信機が転送されるバイトストリームの送信元の長さを知らないということですので、パッケージに固執するためのソリューションは、受信側が知っているように、データサイズを送信すべきデータを送信する前に、送信側を作成する方法についてです無限ループのすべてのデータを受信します。我々は、このモジュールは、データ長がバイトの固定長に送信されるように変換することができる、構造体のモジュールを使用することができます。したがって、クライアントが直前の固定長バイトのコンテンツを受信するメッセージ情報のサイズを受信するたびに、最終的な受信データがあれば、この値に達すると停止し、次の外観を,,受信するが、あまりにも多くはないができるようにするだけ完全なデータを受信します。

我々はまた、辞書を作るために作成したヘッダ構造体を置くことができ、データ・ディクショナリは、内部の本当の、そしてJSONシリアライズ、構造体と一緒にパッケージシリアライズされたデータの後、長さがあります。

思考の問題を解決するために、パッケージをスティック:

  サーバー:

    まず辞書(送信すべきデータのサイズを含む辞書)を行うクライアントに送信

    2.(struct.packを使用して)辞書ヘッダを作ります

    3.辞書ヘッダを送信します

    4.辞書を送ります

    実際のデータ送信

輸入ソケット
 輸入サブプロセス
 輸入構造体の
 インポートJSON

サーバ = socket.socket()  オブジェクト作成 
server.bind((' 127.0.0.1 '、8080))  バインディングIPとポート 
server.listenを(5)  ユーザの半数は、接続プールの制限を要求します

しばらく真:
    CONN、ADDR = server.accept()  待機CONNトランスポート・チャネル(双方向チャネル)のaddrであるクライアントのアドレスです
    しばらく真:
         試してみます
            CMD = conn.recv(1024)  RECV(第一の受信)
            IF LEN(CMD)== 0:エラーなし休暇後のMac、LinuxのクライアントのためのBREAK#サーバは'' Bを受け入れてきたでしょう
            CMD = cmd.decode(' UTF-8 '#のバイナリデータのネットワーク伝送、データ列をデコードに変換され
            データを取得 
            OBJ = subprocess.Popen(CMD、シェル= Trueを、subprocess.PIPE = STDOUT、標準エラー= サブプロセス。 PIPE)
            RES = obj.stdout.read()+ obj.stderr.read()
            D = { ' 名前'' ジェイソン'' FILE_SIZE ':LEN(RES)、' 情報'' asdhjkshasdad ' }
             #はバックバイナリデータ伝送良好に、文字列にダンプ 
            json_d = json.dumps(D)
            1.第1辞書ヘッダ作成 
            ヘッダstruct.pack =(' I ' 、LEN(json_d))
            2の送信辞書ヘッダ 
            conn.send(ヘッダ)   #の送信(第一通路)
            3送信辞書
            conn.send(json_d.encode(' UTF-8 ' ))
            4.再発実際のデータ
            conn.send(RES)

        除くConnectionResetError:
             ブレーク
    はconn.close()

  クライアント:

    1.ヘッダの第1辞書を受け

    2.取得するには、辞書のデータ長を解析

    3.辞書を受け取ります

    4.辞書から取得した実際のデータの長さ

    受信実際のデータ

輸入ソケット
 輸入構造体の
 インポートJSON

クライアント = socket.socket()  オブジェクトを作成 
client.connect((' 127.0.0.1 '、8080))  サーバーのIPとポートを

しばらく真:
    MSG = INPUT(' >>>:').encode(' UTF-8。'#のクライアントを手動で入力する
    IF(MSG)でlen == 0:続行   #は、ユーザが入力しないかどうかを判断し、入力にユーザを続けるに戻り 
    client.send (MSG)   #1 サーバ送信に渡された入力(最初のパス)
    辞書ヘッダ受け入れる1 
    header_dictのclient.recv =(4) RECV(第一受付)
    2辞書を取得したヘッダ長を解析 
    = struct.unpack dict_size(' 私が'、header_dict)[0]  は、インデックス0が結合しなければならない場合アンパック
    3は、データ辞書受信 
    dict_bytes = client.recv(dict_size)を
    dict_json = json.loads(dict_bytes.decode(' UTF-8 ' ))
    4.辞書から情報を取得する
    印刷(dict_json)
    recv_size = 0
    real_data = B '' 
    ながら recv_size <dict_json.get(' FILE_SIZE ':)  REAL_SIZE = 102400件の 
        データ= client.recv(1024 
        real_data + = データ
        recv_size + = LEN(データ)
     の印刷(real_data.decode(' GBK '))

 

おすすめ

転載: www.cnblogs.com/wangcuican/p/11317617.html