Download - 10080分でPythonからIP Messeneger
![Page 1: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/1.jpg)
1
10080分でPythonから
IP Messenger
山田 聡@denzowill#stapy 2016/01/08
![Page 2: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/2.jpg)
2
WHO ARE YOU?
DBエンジニアですノンプログラマPostgreSQLOracle
![Page 3: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/3.jpg)
3
IP Messeneger
http://ipmsg.org/
![Page 4: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/4.jpg)
4
IP Messenger
●1996年くらいからある?●LAN内でメッセージを投げ合うツール●国産●インフラ系の会社では結構みかける?
![Page 5: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/5.jpg)
5
あらすじ:なんかタスク終わったら自動で担当者にIPMSGで通知して欲しいって言われてやってみたら、送信エラーがでなくて苦しんだので、結局自分で実装することになった話
![Page 6: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/6.jpg)
6
![Page 7: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/7.jpg)
7
だいたい2種類あった
●プロトコルをPurePythonで実装● ipmsg.exeをsubprocessで叩く
![Page 8: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/8.jpg)
8
だいたい2種類あった
●プロトコルをPurePythonで実装● ipmsg.exeをsubprocessで叩く
試したが送信先がいなくてもエラーにならない
![Page 9: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/9.jpg)
9
だいたい2種類あった
●プロトコルをPurePythonで実装● ipmsg.exeをsubprocessで叩く
こっち
![Page 10: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/10.jpg)
10
https://github.com/shaung/ipmsg/
![Page 11: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/11.jpg)
11
ipmsg(Pythonパッケージ)
●pipで入る!●試したら送れた!
![Page 12: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/12.jpg)
12
ipmsg(Pythonパッケージ)
●pipで入る!●試したら送れた!● importしてから使うときのDocない…●そーすむずかしい...●結局送信エラーにならない...
![Page 13: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/13.jpg)
13
そうだ自分で、つくろう
![Page 14: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/14.jpg)
14
そうだ自分で、つくろう→1週間以上経過中
![Page 15: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/15.jpg)
15
そうだ自分で、つくろう→1週間以上経過中7 * 24 * 60 = 10080
![Page 16: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/16.jpg)
16
IP Messenegerのプロトコル
●プロトコル● http://ipmsg.org/protocol.txt
●参考になったサイト● http://smart-pda.net/isourou/ipmsg/doc/ipmsg_protocol.html● http://libipmsg.osdn.jp/specification.html#format
国産プロトコルで日本語Docだし比較的シンプル
![Page 17: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/17.jpg)
17
IP Messenegerのメッセージ以下6要素を:で連結して1行にした文字列で表現
● プロトコルバージョン● 1固定
● パケット番号● インクリメント
● 自分の名前● ホスト名● コマンド
● メッセージの属性(32bit)
● メッセージ● 本文とかその他パケットの追加情報
![Page 18: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/18.jpg)
18
1:100:denzow:MyHost:8405280:こんにちは
![Page 19: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/19.jpg)
19
#!/usr/bin/env python# coding:utf-8
import socket
host = 'xxx.xxx.xxx.xxx' # 嫌いな人のIPアドレスport = 2524serversock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 嫌いなあの人に100通送るfor i in range(1,100): send_msg = "1:%s:denzow:MyHost:8405280:こんにちは" % i print 'Send message...[%s]' % send_msg serversock.sendto(send_msg, (host, port))
投げるだけなら簡単
![Page 20: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/20.jpg)
20
$ ./send.py
嫌いな上司にめがけて
![Page 21: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/21.jpg)
21
$ ./send.py
嫌いな上司にめがけて
![Page 22: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/22.jpg)
22
Ψ(`▽´)Ψ
![Page 23: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/23.jpg)
23
でも、上司がオフラインだったら?
![Page 24: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/24.jpg)
24
でも、上司がオフラインだったら?
$ ./send.py$echo $?0
![Page 25: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/25.jpg)
25
でも、上司がオフラインだったら?
$ ./send.py$echo $?0
失敗してても正常終了
![Page 26: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/26.jpg)
26
(´・ω・`)
![Page 27: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/27.jpg)
27
Why?
●そもそもUDP通信●受信完了のメッセージを相手が戻す規定になっていた
![Page 28: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/28.jpg)
28
’・ω・
こんにちは with :IPMSG_SENDMSGIPMSG_SENDCHECKOPT
・_・`
とんでけー
![Page 29: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/29.jpg)
29
’・ω・
こんにちは with :IPMSG_SENDMSGIPMSG_SENDCHECKOPT
・_・`
こんにちは with :IPMSG_SENDMSGIPMSG_SENDCHECKOPT
You got a mail(届いたかしら)
![Page 30: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/30.jpg)
30
’・ω・
こんにちは with :IPMSG_SENDMSGIPMSG_SENDCHECKOPT
・_・`
こんにちは with :IPMSG_SENDMSGIPMSG_SENDCHECKOPT
IPMSG_RECVMSG
とりあえず応答おくるでー
(届いたかしら)
![Page 31: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/31.jpg)
31
’・ω・
こんにちは with :IPMSG_SENDMSGIPMSG_SENDCHECKOPT
・_・`
こんにちは with :IPMSG_SENDMSGIPMSG_SENDCHECKOPT
IPMSG_RECVMSGIPMSG_RECVMSG
届いてた!
![Page 32: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/32.jpg)
32
So..
●送りたいだけなのにリスニング必須●リスニングしつつ送信なのでスレッド?●送信済メッセージも管理必須
![Page 33: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/33.jpg)
33
So..
●送りたいだけなのにリスニング必須●リスニングしつつ送信なのでスレッド?●送信済メッセージも管理必須●受け取ったメッセージのハンドラ必要● IPわからない場合は名前でおくりたい● import して普通に使えるようにしたい●などなど
![Page 34: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/34.jpg)
34
#!/usr/bin/env python# coding:utf-8
import socket
host = 'xxx.xxx.xxx.xxx' # 嫌いな人のIPアドレスport = 2524serversock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 嫌いなあの人に100通送るfor i in range(1,100): send_msg = "1:%s:denzow:MyHost:8405280:こんにちは" % i print 'Send message...[%s]' % send_msg serversock.sendto(send_msg, (host, port))
投げるだけなら簡単
![Page 35: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/35.jpg)
35
while not self.stop_event.is_set(): r, w, e = select.select([self.sock], [self.sock], [], 0) time.sleep(0.1) # print((r, w, e)) # recive message for sk in r: data, (ip, port) = sk.recvfrom(0x80000) # parse message ip_msg = IpmsgMessageParser(ip, port, com.to_unicode(data)) # action for command self.dispatch_action(ip_msg)
# send message if w and self.send_que: # send message loop until que empty. while self.send_que: # FIFO send_msg = self.send_que.popleft() logger.debug("To[%s:%s]" % (send_msg.addr, send_msg.port)) [logger.debug("\t"+x) for x in send_msg.check_flag()] logger.debug(send_msg.get_full_message()) self.sock.sendto(send_msg.get_full_message(), (send_msg.addr, send_msg.port))
if send_msg.is_sendmsg(): # for check sendmsg success # if long time in the sended que, the message must be failed. send_msg.born_time = datetime.datetime.now() self.sended_que.append(send_msg)
self._cleanup_ques()
投げるだけなら簡単だったのに
サーバ処理のメインループだけで
これ
![Page 36: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/36.jpg)
36
while not self.stop_event.is_set(): r, w, e = select.select([self.sock], [self.sock], [], 0) time.sleep(0.1) # print((r, w, e)) # recive message for sk in r: data, (ip, port) = sk.recvfrom(0x80000) # parse message ip_msg = IpmsgMessageParser(ip, port, com.to_unicode(data)) # action for command self.dispatch_action(ip_msg)
# send message if w and self.send_que: # send message loop until que empty. while self.send_que: # FIFO send_msg = self.send_que.popleft() logger.debug("To[%s:%s]" % (send_msg.addr, send_msg.port)) [logger.debug("\t"+x) for x in send_msg.check_flag()] logger.debug(send_msg.get_full_message()) self.sock.sendto(send_msg.get_full_message(), (send_msg.addr, send_msg.port))
if send_msg.is_sendmsg(): # for check sendmsg success # if long time in the sended que, the message must be failed. send_msg.born_time = datetime.datetime.now() self.sended_que.append(send_msg)
self._cleanup_ques()
投げるだけなら簡単だったのに
ソケットをselectでwatchして
![Page 37: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/37.jpg)
37
while not self.stop_event.is_set(): r, w, e = select.select([self.sock], [self.sock], [], 0) time.sleep(0.1) # print((r, w, e)) # recive message for sk in r: data, (ip, port) = sk.recvfrom(0x80000) # parse message ip_msg = IpmsgMessageParser(ip, port, com.to_unicode(data)) # action for command self.dispatch_action(ip_msg)
# send message if w and self.send_que: # send message loop until que empty. while self.send_que: # FIFO send_msg = self.send_que.popleft() logger.debug("To[%s:%s]" % (send_msg.addr, send_msg.port)) [logger.debug("\t"+x) for x in send_msg.check_flag()] logger.debug(send_msg.get_full_message()) self.sock.sendto(send_msg.get_full_message(), (send_msg.addr, send_msg.port))
if send_msg.is_sendmsg(): # for check sendmsg success # if long time in the sended que, the message must be failed. send_msg.born_time = datetime.datetime.now() self.sended_que.append(send_msg)
self._cleanup_ques()
投げるだけなら簡単だったのに
パケットがきてたらパケットをメッセージにして
アクション
![Page 38: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/38.jpg)
38
while not self.stop_event.is_set(): r, w, e = select.select([self.sock], [self.sock], [], 0) time.sleep(0.1) # print((r, w, e)) # recive message for sk in r: data, (ip, port) = sk.recvfrom(0x80000) # parse message ip_msg = IpmsgMessageParser(ip, port, com.to_unicode(data)) # action for command self.dispatch_action(ip_msg)
# send message if w and self.send_que: # send message loop until que empty. while self.send_que: # FIFO send_msg = self.send_que.popleft() logger.debug("To[%s:%s]" % (send_msg.addr, send_msg.port)) [logger.debug("\t"+x) for x in send_msg.check_flag()] logger.debug(send_msg.get_full_message()) self.sock.sendto(send_msg.get_full_message(), (send_msg.addr, send_msg.port))
if send_msg.is_sendmsg(): # for check sendmsg success # if long time in the sended que, the message must be failed. send_msg.born_time = datetime.datetime.now() self.sended_que.append(send_msg)
self._cleanup_ques()
投げるだけなら簡単だったのに
送信キューにメッセージがあればFIFOで処理
![Page 39: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/39.jpg)
39
while not self.stop_event.is_set(): r, w, e = select.select([self.sock], [self.sock], [], 0) time.sleep(0.1) # print((r, w, e)) # recive message for sk in r: data, (ip, port) = sk.recvfrom(0x80000) # parse message ip_msg = IpmsgMessageParser(ip, port, com.to_unicode(data)) # action for command self.dispatch_action(ip_msg)
# send message if w and self.send_que: # send message loop until que empty. while self.send_que: # FIFO send_msg = self.send_que.popleft() logger.debug("To[%s:%s]" % (send_msg.addr, send_msg.port)) [logger.debug("\t"+x) for x in send_msg.check_flag()] logger.debug(send_msg.get_full_message()) self.sock.sendto(send_msg.get_full_message(), (send_msg.addr, send_msg.port))
if send_msg.is_sendmsg(): # for check sendmsg success # if long time in the sended que, the message must be failed. send_msg.born_time = datetime.datetime.now() self.sended_que.append(send_msg)
self._cleanup_ques()
投げるだけなら簡単だったのに
送信ミスとかでキューに長くのこった
メッセージ等のクリーンアップ
![Page 40: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/40.jpg)
40
よかったら
●GitHubにあげるだけあがってます● https://github.com/denzow/ipymessenger
●Docとコメントは週明けに日本語に変更● IPMSGは海外需要ない気がしてきたので…
●送信は実装済●受信は週明けに実装(希望)
![Page 41: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/41.jpg)
41
つまり:なんかタスク終わったら自動で担当者にIPMSGで通知して欲しいって言われてやってみたら、送信エラーがでなくて苦しんだので、結局自分で実装することになった話
![Page 42: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/42.jpg)
42
つまり:なんかタスク終わったら自動で担当者にIPMSGで通知して欲しいって言われてやってみたら、送信エラーがでなくて苦しんだので、結局自分で実装することになった話
人の、10080分が短縮できれば幸いです
![Page 43: 10080分でPythonからIP Messeneger](https://reader030.vdocuments.pub/reader030/viewer/2022021419/5877440d1a28ab342e8b770b/html5/thumbnails/43.jpg)
43
ありがとうございました。