pythonネットワークプログラミング学習ノート(3):socketネットワークサーバ

6734 ワード

1、TCP接続の確立方法
クライアントはTCP接続を確立する際に一般的に2ステップを必要とし、サーバのこのプロセスは4ステップを必要とし、具体的には以下の比較を参照してください.
ステップ
TCPクライアント
TCPサーバ
最初のステップ
ソケットオブジェクトの作成
ソケットオブジェクトの作成
ステップ2
connect()を呼び出してサーバとの接続を確立する
SOcketオプションの設定(オプション)
ステップ3
なし
1つのポートにバインド(指定されたNICでも構いません)
ステップ4
なし
リスニング接続
次の4つのステップの作成方法を具体的に説明します.
最初のステップは、socketオブジェクトを確立します.ここではクライアントと同様に、次のようになります.
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
ステップ2では、socketオプションを設定および取得します.
pythonはsetsockopt()とgetsockopt()を定義し、1つは設定オプションであり、1つは設定される.ここでは主にsetsockopt()を使用し、具体的な構造は以下の通りである.
setsockopt(level,optname,value)
levelは、どのオプションが使用されるかを定義します.通常はSOL_SOCKETは、使用中のsocketオプションを意味します.また、特定のプロトコル番号を設定することでプロトコルオプションを設定することもできますが、特定のオペレーティングシステムでは、ほとんどのプロトコルオプションが明確であるため、簡単にするためにモバイルデバイスのために設計されたアプリケーションにはあまり使用されません.
optnameパラメータは、使用する特別なオプションを提供します.使用可能なオプションの設定は、OSによって若干異なります.レベルがSOLを選択した場合SOCKET、一般的なオプションは次の表を参照してください.
オプション
意味
期待値
SO_BINDTODEVICE
SOcketは、特定のネットワークインタフェース(NIC)のみで有効にできます.携帯機器ではないかもしれません
1つの文字列は、デバイスの名前または空の文字列にデフォルト値を返します.
SO_BROADCAST
ブロードキャストアドレスがパケットを送信および受信することを許可する.UDPのみ有効です.ブロードキャストパケットの送信と受信方法
ブール整数
SO_DONTROUTE
ルータとゲートウェイを介してパケットを外部に送信することは禁止されています.これは主に安全のためにイーサネット上でUDP通信を行う方法である.宛先アドレスがどんなIPアドレスを使用しても、データがローカルネットワークから離れることを防止できます.
ブール整数
SO_KEEPALIVE
TCP通信のパケットは連続性を保つことができる.これらのパケットは、情報伝送がない場合に、通信の双方に接続が保持されていると判断させることができる
ブール整数
SO_OOBINLINE
受信した不正常なデータを正常なデータと見なすことができ、すなわち、標準的なrecv()の呼び出しによってこれらのデータを受信することができる.
ブール整数
SO_REUSEADDR
SOcketがオフになると、ローカル側のsocketに使用されるポート番号はすぐに再利用できます.通常、再利用できるのは、システム定義の時間が経過した後だけです.
ブール整数
本節では学習にSO_を用いた.REUSEADDRオプション、具体的な書き方は:
S.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)ここでvalueは1に設定され、SO_REUSEADDRはTRUEとしてマークされ、オペレーティングシステムは、サーバsocketが閉じられたか、サーバプロセスが終了した後にすぐにサーバのポートを解放します.そうしないと、オペレーティングシステムは数分保持します.
次の方法では、システムのpythonでサポートされているsocketオプションのリストを示します.
 
  
import socket
solist=[x for x in dir(socket) if x.startswith('SO_')]
solist.sort()
for x in solist:
    Print x

ステップ3:socketのバインド
バインディングは、サーバにポート番号を要求します.
S.bind((host,port))は、hostがサーバipであり、通常は空であり、特定のipアドレスにバインドされてもよい.Portはポート番号です.
ステップ4:接続をリスニングします.
listen()関数を使用して接続をリスニングします.この関数には、サーバが実際に接続を処理するときに、キュー内でどれだけの未解決(待機)接続が待機できるかを示すパラメータが1つしかありません.1つの約束として、多くの人が5に設定されています.例えば、s.listen(5)2、簡単なTCPサーバの例これは簡単なTCPサーバとクライアントを確立する.サーバー側:TCP応答サーバー、クライアントと接続を確立した後に、サーバーはクライアントipとポートを表示して、同時に受信したクライアント情報と'I get it!'クライアントに送信され、新しい情報がクライアントに入力されるのを待っています.クライアント:TCPクライアントは、まずサーバipアドレスを入力し、次に情報を入力し、車に戻った後にサーバからの返信情報を取得し、サーバからのメッセージ送信を待って終了します.具体的なコードは以下の通りである:サーバ側:tcpserver.py
 
  
# -*- coding: cp936 -*-
##tcp , , ip , 'I get it!' , 。
##@
import socket,traceback
host=''
port=12345
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind((host,port))
s.listen(1)

while 1:
    try:
        clientsock,clientaddr=s.accept()
    except KeyboardInterrupt:
        raise
    except:
        traceback.print_exc()
        continue
    try:
        print " :",clientsock.getpeername()
        while 1:
            data=clientsock.recv(4096)
            if not len(data):
                break
            print clientsock.getpeername()[0]+':'+str(data)
            clientsock.sendall(data)
            clientsock.sendall("
I get it!
")
            t=raw_input('input the word:')
            clientsock.sendall(t)
    except (KeyboardInterrupt,SystemExit):
        raise
    except:
        traceback.print_exc()

    try:
        clientsock.close()
    except KeyboardInterrupt:
        raise
    except:
        traceback.print_exc()


クライアント:tcpclient.py
 
  
# -*- coding: cp936 -*-
##tcp , ip , , , 。
##@
import socket,sys
port=12345
host=raw_input(' ip:')
data=raw_input(' :')
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
try:
    s.connect((host,port))
except:
    print ' !'
s.send(data)
s.shutdown(1)
print ' 。'
while 1:
    buf=s.recv(4096)
    if not len(buf):
        break
    sys.stdout.write(buf)

実行結果:
クライアントはhelloを入力して、サーバー側はokを入力して、具体的に結果を表示します:
サーバ側:
接続元:('127.0.0.1',1945)127.0.0.1:helloInput the world:okクライアント:入力サーバip:127.0.0.1送信する情報を入力:hello送信完了.helloI get it!ok
3、UDPサーバー
UDPサーバの確立はTCPと類似しており、具体的には以下のように比較される.
ステップ
UDP
TCP
最初のステップ
ソケットオブジェクトの作成
ソケットオブジェクトの作成
ステップ2
ソケットオプションの設定
ソケットオプションの設定
ステップ3
ポートにバインド
ポートにバインド
ステップ4
Recvfrom()
リスニング接続
ここではUDPを利用してタイムサーバを構築する.
コードは次のとおりです.
サーバ側;serverudp.py
 
  
# -*- coding: cp936 -*-
##UDP , ,
##@
import socket,traceback,time,struct
host=''
port=12345
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind((host,port))

while 1:
    try:
        message,address=s.recvfrom(8192)
        secs=int(time.time())
        reply=struct.pack("!I",secs)
        s.sendto(reply,address)
    except (KeyboardInterrupt,SystemExit):
        raise
    except:
        traceback.print_exc()


クライアント:clientudp.py
 
  
# -*- coding: cp936 -*-
##udp , ,
##@
import socket,sys,struct,time
host=raw_input(' :')
port=12345
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
s.sendto('',(host,port))
print " ……"
buf=s.recvfrom(2048)[0]
if len(buf)!=4:
    print " %d:%s"%(len(buf),buf)
    sys.exit(1)
secs=struct.unpack("!I",buf)[0]
print time.ctime(int(secs))

実行結果:
まずサーバ側を実行し、次にクライアントを実行します.C:\>python clientudp.py  ##clientudp.pyプログラムはcディスクの下に保存してサーバーのアドレスを入力します:127.0.0.1返事を待つ......Mon Aug 06 17:09:17 2012