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モードでやりきるのは難しすぎる
ということです。
では、ノンブロッキングだとどうなるかやってきましょう。
長くなりました。次回にします。