Python de socket(1)

SOCKETを考える

SOCKET、やっかいですよ。
始めてのSOCKETプログラム、2002年くらいだったかな。
Windowsによる分散処理システムを作ったとき。
『最強』のメタファとして、『Fedor』なんて名前をつけましたよ。

何がやっかいかっていうと、、ちょっと羅列して見ます。

WindowsとLinuxと違ったり。
Winsockがどうした、バークレーソケットが云々とか。
タイミングによって、正常なのに例外とか。
sleepを入れないと取りこぼしたりとか。
ブロッキングするかしないか悩んだり。
しょうがない。signalするか!って思ったり。
Pythonだと、最後の最後に、C++みたいに言う事聞いてくれない!とか。

さらに厄介なのは、

PythonでThreadを強制的に終了できないっぽい

ってのもあると、アウトプロセスでプロセスにした時の問題とか。

そう、ここらへんで一度整理してみましょう。

ブロッキングで考える

まず、ブロッキングで考えてみます。
何も考えずにプログラムすると、そうなるのかな。
では行ってみましょう。
とりあえず、
●サーバ側:送信+受信
●クライアント側:送信+受信
で、簡単にメッセージングしてみます。

#-------------------------------------------------------
import sys
import socket
import time
import multiprocessing
import threading
#-------------------------------------------------------
if __name__ == '__main__':
	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	s.setsockopt(socket.SOL_SOCKET,socket.SO_SNDBUF,80)
	s.setsockopt(socket.SOL_SOCKET,socket.SO_RCVBUF,80)
	s.bind(("0.0.0.0", 60009))
	s.listen(10)
	s.setblocking(True)
	print("accept開始")
	conn,addr = s.accept()	#ここでとまる
	dat		= conn.recv(4)
	print("dat",dat)
	a = conn.send(b"1234567890")
	print("10秒後に終了",a)
	time.sleep(10)
	s.close()
#-------------------------------------------------------
import sys
import socket
import time
import multiprocessing
import threading
#-------------------------------------------------------
if __name__ == '__main__':
	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	s.setsockopt(socket.SOL_SOCKET,socket.SO_SNDBUF,80)
	s.setsockopt(socket.SOL_SOCKET,socket.SO_RCVBUF,80)
	s.setblocking(True)
	#-------------------------------------
	print("開始します")
	#-------------------------------------
	print("connectします")
	a = s.connect(('127.0.0.1',60009))
	print("connect:",a)
	#-------------------------------------
	print("sendします")
	a = s.send(b"ZZ123")
	print("send:",a)
	#-------------------------------------
	print("recvします")
	a = s.recv(10)
	print("a:",a)
	#-------------------------------------
	print("10秒後に終了")
	time.sleep(10)
	s.close()

まぁ、当然、普通にできますよね。(o^^o)

ではここで、SV側のrecvを何度もやってみましょう。
CL側は、5バイトの文字を送信んしてるわけですね

	a = s.recv(10)
	print("a:",a)
	a = s.recv(10)
	print("a:",a)
	a = s.recv(10)
	print("a:",a)
	a = s.recv(10)
	print("a:",a)
	a = s.recv(10)
	print("a:",a)

ハイ!ここでBlockingです。まぁ仕方ないですね。
こないものをrecvしようとしてるので。

では、CL側から連続してsendしてみましょう

	a = s.send(b"ZZ123")
	print("send:",a)
	a = s.send(b"*****")
	print("send:",a)

はい。ちゃんと送信されてますね。
連続のsendの間にsleepを入れてみましょう。

	a = s.send(b"ZZ123")
	print("send:",a)
	time.sleep(5)
	a = s.send(b"*****")

もうSV側のrecvが完了してしまい、CL側のsendがBlockingしてしまいます。
まぁあたりまえですね。

問題は、、そうです。

もうバッファにないかどうかどうやって確かめるのだ?

ってことです。

そう、早い話、

Blockingモードでやりきるのは難しすぎる

ということです。
では、ノンブロッキングだとどうなるかやってきましょう。

長くなりました。次回にします。

コメントする

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です