七.Pythonネットワークプログラミング

5391 ワード

ネットワークプログラミング
Socketの紹介
Socketは、アプリケーション層がTCP/IPプロトコルファミリーと通信する中間ソフトウェア抽象層であり、インタフェースのセットである.設計モードでは、Socketは複雑なTCP/IPプロトコルファミリーをSocketインタフェースの後ろに隠し、ユーザーにとって簡単なインタフェースのセットがすべてであり、Socketにデータを組織させ、指定されたプロトコルに合致させる.
Socketは汎用的なネットワークプログラミングインターフェースであり,ネットワーク階層とは一対一の対応関係がない.
Pythonではsocketを提供しています.py標準ライブラリ、非常に下位のインタフェースライブラリ.プロトコルファミリー:AFはAddress Familyを表し、socket()の最初のパラメータに使用されます.
AF_INET IPV4AF_INET IPV6
Socketには2種類あります
  • SOCK_STREAMは接続されたストリームソケットに面している.TCPプロトコル
  • SOCK_DGRAM無接続データメッセージソケット、UDPプロトコル
  • TCPプログラミング
    Socketプログラミングは、両端が必要で、一般的にはサービス側、クライアントが必要です.
    TCPサービス側ステップ:1)Socketオブジェクトの作成2)IPアドレスAddressとポートPortをバインドします.Bind()メソッドポートに対応するプロセス3)はリスニングを開始し,指定されたIPポートでリスニングする.Listen()メソッド.4)データを転送するためのSocketオブジェクトsocketを取得する.accept()->(socket object,address info)acceptメソッドは、クライアントが接続を確立するのを待つのをブロックし、Socketオブジェクトとクライアントアドレスの2元グループを返します.アドレスはリモートクライアントのアドレスであり、IPV 4は二元グループ(clientaddr,port)5)受信データである:recv(bufsize[,flags])バッファを使用してデータ送信データを受信する:send(bytes)送信データ6)リソースを閉じる
    import time
    #TCP Server
    sock = socket.socket() #  IPv4,TCP 
    ip = '127.0.0.1'
    port = 9999 #   
    addr = (ip, port)
    sock.bind(addr) #   IP   
    sock.listen()  #  
    conn, addrinfo = sock.accept() #    socket         ,    
    data = conn.recv(1024) #     
    print(data)
    msg = '       {}'.format(data.decode())
    conn.send(msg.encode()) #       
    conn.close()
    sock.close()

    ソケットの一般的な方法
    方法
    説明
    socket.recv(bufsize[, flags])
    データの取得、デフォルトはブロック方式
    socket.recvfrom(bufsize[, flags])
    データを取得し、二元グループ(bytes,address)を返します.
    socket.recv_into(buffer[, nbytes[, flags]])
    nbytesデータを取得したらbufferに格納します.nbytesが指定または0を指定していない場合は、bufferサイズのデータをbufferに格納します.受信バイト数を返す
    socket.recvfrom_into(buffer[, nbytes[, flags])
    データを取得し、bufferに2元グループ(bytes,address)を返します.
    socket.send(bytes[, flags)
    TCP送信データ
    socket.sendall(bytes[, flags)
    TCPはすべてのデータを送信し、Noneに正常に戻ります.
    s.sendto(string[,flags],address)
    UDP送信データ
    socket.sendfile(file, offset=0, count=None)
    EOFまでファイルを送信し、高性能のosを使用します.sendfileメカニズムは、送信されたバイト数を返します.
    socket.makefile(mode='r', buffering=None,* ,encoding=None, errors=None, newline=None)
    ソケットに関連付けられたファイルオブジェクトを作成します.
  • makefile例
  • import threading
    import socket
    import logging
    import time
    logging.basicConfig(level=logging.INFO, format='%(thread)d %(threadName)s %(message)s')
    
    #TCP Server
    sock = socket.socket() #  IPV4 TCP
    ip = '127.0.0.1'
    port = 9999 #   
    addr = (ip, port)
    sock.bind(addr) #   IP   
    sock.listen()  #  
    conn, addrinfo = sock.accept() #    socket         ,    
    
    f = conn.makefile(mode='rw')
    line = f.read(10)
    print(line)
    f.write('Return your msg:{}'.format(line))
    f.flush()
    f.close()

    UDPサービス:
    TCPとほぼ同様である、具体的には以下の1)socketオブジェクトを作成する2)IPとport 3をバインド)送信データ受信データ:socket.recvfrom(bufsize[,flags])送信データ:socket.sendto(string,address)4)リソースUDPクライアントの解放:1)socketオブジェクトの作成2)送信データ:socket.sendto(string,address)あるアドレスに送信ある情報3)リソースを解放する
    Socketserver
    socketプログラミングはあまりにも下位なので、多くの言語がsocket下位APIをパッケージ化しています.Pythonのパッケージはsocketserverモジュールです.
    SocketServerは、ネットワーク・サーバの作成をシンプル化します.4つの同期クラスTCPServer、UDPServer、UnixStreamServer、UnixDatagramServerの2つのMixinクラスForkingMixin、ThreadingMixinが非同期をサポートしています.class ForingUDPServer(ForkingMixin, UDPServer): Passclass ForingTCPServer(ForkingMixin, TCPServer): Passclass ThreadingUDPServer(ThreadingMixin, UDPServer): passclass ThreadingTCPServer(ThreadingMixin, TCPServer): pass
    プログラミングインターフェース:
  • socketserver.BaseServer(server_address, RequestHandlerClass)

  • サーババインディングのアドレス情報と要求を処理するRequestHandlerClassクラスが必要です.
  • RequestHandlerClassクラスは、BaseRequestHandlerClassのサブクラスである必要があります
  • BaseRequestHandlerClass

  • ユーザ接続(socket接続)のユーザ要求処理クラスは、サーバインスタンスがユーザ要求を受信すると、最後にインスタンス化されます.初期化後、request、client_の3つの構造パラメータが送られます.address、serverは後でBaseRequestHandlerClassクラスのインスタンスで通過できます.self.requestはクライアントに接続するsocketオブジェクトselfである.serverはTCPServer自体のselfである.client_addressはクライアントアドレスです.3つの関数が一度に呼び出され、サブクラスが上書きされます.
    BaseRequestHandlerClass: #        
        def setup(self): #        
            pass
        def handle(self): #       
            pass
        def finish(self): #       
            pass

    import socketserver
    import threading
    #       
    class MyHandler(socketserver.BaseRequestHandler):
    
        def setup(self):
            super().setup()
            # TODO
            self.event = threading.Event()
    
        def handle(self):
            super().handle()
            print(self.server, self.client_address, self.request)
            #   ,    ,         
            while not self.event.is_set():
                data = self.request.recv(1024).decode()
                msg = "Your msg={}".format(data)
                print(msg)
                self.request.send(msg.encode())
                if not data:
                    break
    
        def finish(self):
            super().finish()
    
    
    #            
    ADDR = ('127.0.0.1', 9999)
    server = socketserver.ThreadingTCPServer(ADDR, MyHandler)
    server.serve_forever()
    
    server.shutdown()
    server.server_close()

    まとめ:サーバを作成する手順1.要求処理クラスは、BaseRequestHandlerクラスをサブクラス化し、handle()メソッドを上書きすることによって作成され、このメソッドは、受信要求2を処理する.サーバクラスをインスタンス化し、サーバのアドレスとリクエストハンドラクラスを渡す必要があります.3.サーバオブジェクトを呼び出すhandle_request()またはserver_forever()メソッド4.呼び出しsocket_close()はソケットを閉じます.shutdown()メソッド停止待ちforever()メソッド