学习用书:《python 网络编程基础》作者John Goerzen
第一部分底层网络学习
Python提供了访问底层操作系统Socket接口的全部方法,需要的时候这些接口可以提供灵活而强有力的功能。
(1)基本客户端操作
在《python 网络编程基础》一书中,作者列出了一个简单的Python客户端程序,具体如下:
filename=sys.argv[2]
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((host,port))
s.sendall(filename+"\r\n")
while 1:
buf=s.recv(2048)
if not len(buf):
break
sys.stdout.write(buf)
该程序实现的是Gopher协议,实现从主机上请求相关文档的功能。(Gopher是Internet上一个非常有名的信息查找系统,它将Internet上的文件组织成某种索引,很方便地将用户从Internet的一处带到另一处。在WWW出现之前,Gopher是Internet上最主要的信息检索工具,Gopher站点也是最主要的站点。但在WWW出现后,Gopher失去了昔日的辉煌。现在它基本很少被使用。)
于是,我按照书上的语句进行了一下测试,在dos下运行python gopherclient.py quux.org。但是系统提示为
Traceback (most recent call last):
File "gopherclient.py", line 5, i
filename=sys.argv[2]
IndexError: list index out of range
看了一下,sys.argv只有两个元素['gopherclient.py', 'quux.org/']所以filename=sys.argv[2]就超出下界了。可是为什么会出现这个原因呢?是书里面写错了吗,因为我也是初学socket,不是很了解,所以我也是没有找到原因,如果哪位大牛知道是什么原因,希望能给讲解一下。
(2)基本服务器操作
《python 网络编程基础》一书中同样给出了一个简单的服务器程序,具体如下:
print "Server is running on port %d;press Ctrl-C to terminate." %port
while 1:
clientsock,clientaddr=s.accept()
clientfile=clientsock.makefile('rw',0)
clientfile.write("welcome,"+str(clientaddr)+'\n')
clientfile.write("Please enter a string:")
line=clientfile.readline().strip()
clientfile.write("You entered %d characters.\n" %len(line))
clientfile.close()
clientsock.close()
プログラムを実行すると、「サーバーはポート 51423 で実行されています: Ctrl-C を押して終了します」というメッセージが表示されます。このとき、別のマシンを介してこのマシンの 51423 ポートに Telnet 127.0.0.1:51423 のように Telnet 接続すると、「welcome 127.0.0.1 ****,please enter a string:」というメッセージが表示されます。 その後、いくつかの文字を入力すると、入力した文字数が返されます。
プログラムの分析は次のとおりです:
1. まずソケット モジュールをインポートし、ホストとポートに値を割り当てます。
2.socket.socket() を呼び出してソケットを作成し、それを s に割り当てます。ソケット.ソケット(ドメイン、タイプ、プロトコル).ドメインパラメータの値は、AF_UNIX、AF_LOCAL、AF_INET、PF_UNIX、PF_LOCAL、PF_INETです。これらの値のうち、AF_UNIX=AF_LOCAL、PF_UNIX=PF_LOCAL、AF_LOCAL=PF_LOCAL、AF_INET=PF_INET。一般に、AF は ADDRESS FAMILY アドレス ファミリを表し、PF は PROTOCOL FAMILY プロトコル ファミリを表しますが、2 つのマクロ定義は同じであるため、どちらを使用しても問題ありません。パラメータ type はソケットのタイプを指定します。SOCK_STREAM は、順序付けされた信頼性の高い双方向の接続ベースのバイト ストリームを提供します。 SOCK_DGRAM はデータグラムをサポートします。 SOCK_SEQPACKET は、順序付けされた信頼性の高い双方向の接続ベースのデータグラム通信を提供します。 SOCK_RAW は、生のネットワーク プロトコルへのアクセスを提供します。 SOCK_RDM は信頼性の高いデータグラム層を提供しますが、順序付けは保証しません。プロトコルは通常0がかかります(なぜ0がかかるのかはわかりません。理解できたら書き留めます)。
3. s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)。 setsockopt() 関数は、任意のタイプおよびステータスのソケットのオプション値を設定するために使用されます。オプションはさまざまなプロトコル層に存在しますが、この関数は最上位の「ソケット」レベルでのみオプションを定義します。オプションは、緊急データを通常のデータ ストリームで受信するかどうか、ブロードキャスト データをソケットから送信できるかどうかなど、ソケットの動作に影響します。 この関数の最初のパラメータはプロトコル層パラメータで、オプションにアクセスするプロトコル スタックを指定します。通常、次のいずれかを使用する必要があります:
SOL_SOCKET ソケット層オプションにアクセス
SOL_TCP TCP 層オプションにアクセス
2 番目のパラメータは最初のパラメータに対応します。最初のパラメータはプロトコル層レベルを決定し、2 番目のパラメータはプロトコル層の下のオプションの組み合わせを決定します。 SOL_SOCKET のオプションの組み合わせは次のとおりです。
プロトコル層オプション名
SOL_SOCKET SO_REUSEADDR
SOL_SOCKET SO_KKEPALIVE
SOL_SOCKET SO_LINGER
SOL_SOCKET SO_BROADCAST
SOL_SOCKET SO_OOBINLINE
SOL_ソケット SO _SNDBUF
SOL_SOCKET SO_RCVBUF
SOL_SOCKET SO_TYPE
SOL_SOCKET SO_ERROR
いくつかの特定の組み合わせは、http://wenku.baidu.com/view/23013b7101f69e3143329402.html
3 番目のパラメーターは 1 に設定されています。ここではよくわかりません。つまり、1 を 50 に変更してみましたが、結果は同じでした。 0 に変更しても違いはありません。専門家の方からアドバイスをいただければ幸いです。
4. s.bind((host,port)) はホストポートをバインドします。
5. s.listen(1): listen 関数は、アクティブな接続ソケットを使用して接続されたソケットになり、プロセスが他のプロセスからの要求を受け入れてサーバー プロセスになることができます。 TCP サーバー プログラミングでは、リッスン関数はプロセスをサーバーに変え、対応するソケットがパッシブ接続になるように指定します。ここでのパラメータには、ネットワークの詳細が含まれます。プロセスが接続要求を 1 つずつ処理している間に、他の接続要求が発生する可能性があります。 TCP 接続はプロセスであるため、同時に接続しようとするユーザーが多すぎるために、サーバー プロセスが接続要求を迅速に完了できない場合があります。この状況が発生した場合、サーバー プロセスはカーネルにどのように処理してもらいたいでしょうか?カーネルは、これらの完了した接続を追跡するために独自のプロセス空間にキューを維持しますが、サーバー プロセスはまだ処理や進行中の接続を引き継いでいないため、カーネルはそのようなキューを任意に大きくすることはできないため、サイズに上限を設ける必要があります。 。このバックログは、この値を上限として使用するようにカーネルに指示します。確かにサーバプロセスが任意に値を指定することはできず、カーネルには許容範囲がある。この範囲は実装に依存します。通常、この値は 30 未満になります。ここで 1 に設定すると、一度に最大 1 つの接続が処理を待機していることになります。
6. while ループは accept() 関数から始まります。プログラムはクライアントの接続後にソケットを閉じます。クライアントが接続すると、accept は、新しい接続クライアント ソケットとクライアントの IP アドレスとポート番号という 2 つの情報を返します。上記の例で、clientsock と clientaddr を出力する print ステートメントを追加すると、clientsock がソケット.socketobject, clientaddr=('client Ip', port) であることがわかります。ファイル オブジェクトは後続のループで使用され、サーバーはいくつかの紹介情報を表示し、クライアントから文字列を読み取り、応答を表示し、最後にクライアント ソケットを閉じます。