ネット上には情報たくさんありますのでここでSocket通信とはなにかを説明しなくてよいだと思います。
https://qiita.com/megadreams14/items/32a3eed4661e55419e1c
http://research.nii.ac.jp/~ichiro/syspro98/socket.html
https://qiita.com/tatsuya4150/items/474b60beed0c04d5d999
PythonではSocketのモジュールがあり、今回はこれを使います。
サンプルコードはサーバー側とクライアント側に分けてます。
簡単なメッセージを投げてみよう
まずサーバがずっとリクエストが待って、クライアントがリクエストきたらwelcome to my server!を返しします。
サーバー側
import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((socket.gethostname(),8020))
s.listen(5)
while True:
clientsocket,address=s.accept()
print('Connection from {} is established'.format(address))
clientsocket.send(bytes('welcome to my server!','utf8'))
clientsocket.close()
クライアント側
import socket
#a stream of data is coming, you should define how long of your track.
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((socket.gethostname(),8020))
#buffer
msg=s.recv(1024)
#beacause we are receiving the byte, we need to decode the bytes.
print(msg.decode('utf-8'))
s.close()
うん~なんだか行きそうですね。
クライアント側のmsg=s.recv(1024)の1024ちょっと気になるね。これを(1)にしたらどうになるのかな。
import socket
#a stream of data is coming, you should define how long of your track.
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((socket.gethostname(),8020))
#buffer
Entire_msg=''
while True:
msg=s.recv(1)
print(msg)
Entire_msg+=msg.decode('utf-8')
if len(msg) <=0 :
break
#beacause we are receiving the byte, we need to decode the bytes.
print(Entire_msg)
s.close()
なるほど、msg=s.recv(1)は毎回もらうのデータサイズを決めるってことだね~
FIX_HEADERをつけてみよう
三菱CPUのMC-Protocolとか色々なHeaderがあるじゃない?それはなになにFrameとかデータのアドレスをどこから取るとか、
何個アドレス取るとか。ここで仮に簡単FIX_HEADERを作ってみますね~
FIX_HEADERの仕様:
長さ:20
MESSAGEの文字列の長さ+SPACE
例えば、Welcome to the serverなら、21 Welcome to the serverになります。
import socket
import time
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((socket.gethostname(),8020))
s.listen(5)
FIX_HEADER=20
while True:
msg='Welcome to the server'
le= str(len(msg))
msg=le+(FIX_HEADER-(len(str(len(msg)))))*' '+msg
clientsocket,address=s.accept()
print('Connection from {}'.format(address))
clientsocket.send(bytes(msg,'utf8'))
こっちはクライアント側です:
import socket
FIX_HEADER=20
#a stream of data is coming, you should define how long of your track.
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((socket.gethostname(),8020))
while True:
#buffer
full_msg=''
new_msg=True
while True:
msg=s.recv(10)
if new_msg:
print('new message:{}'.format(msg[:FIX_HEADER]))
print(msg[:FIX_HEADER])
msglen=int((msg[:FIX_HEADER]))
new_msg=False
full_msg+=msg.decode('utf-8')
if len(full_msg)-FIX_HEADER == msglen:
print('All Recv..')
print(full_msg[FIX_HEADER:])
new_msg=True
full_msg=''
print(full_msg)
Python Objectを送ってみよう
ここで使われてるのPythonのPickleモジュールです。サンプルコードは辞書を使うですが、
場合によってJSONでもLISTでもなんでもOKです!
こちはサーバ側です:
import socket
import time
import pickle
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind((socket.gethostname(),8020))
s.listen(5)
FIX_HEADER=20
while True:
# msg='Welcome to the server'
d={1:'Hello',2:'I am here'}
msg=pickle.dumps(d)
print(msg)
le= str(len(msg))
header=(((le+(FIX_HEADER-(len(str(len(msg)))))*' ')))
header2=bytes(header.encode())
msg=header2+msg
clientsocket,address=s.accept()
print('Connection from {} is established on {}'.format(address,time.time()))
clientsocket.send(msg)
クライアント側:
import socket
import pickle
FIX_HEADER=20
#a stream of data is coming, you should define how long of your track.
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((socket.gethostname(),8020))
while True:
#buffer
full_msg=b''
new_msg=True
while True:
msg=s.recv(10)
if new_msg:
print('new message:{}'.format(msg[:FIX_HEADER]))
print('*')
msglen=int((msg[:FIX_HEADER]))
print(msglen)
new_msg=False
full_msg+=msg
print(full_msg)
if len(full_msg)-FIX_HEADER == msglen:
print('All Recv..')
print(full_msg[FIX_HEADER:])
d=pickle.loads(full_msg[FIX_HEADER:])
new_msg=True
print('*')
print(d)
以上になりますが、今回ここでSocket一回自分の手でやってみたらPLCとかでなんでここでこんな設定にならないと
だめなんだ?とか少しわかると気がします。