10080分でpythonからip messeneger

43
1 10080分で Pythonから IP Messenger 山田 聡@denzowill #stapy 2016/01/08

Upload: satoshi-yamada

Post on 12-Jan-2017

1.466 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: 10080分でPythonからIP Messeneger

1

10080分でPythonから

IP Messenger

山田 聡@denzowill#stapy 2016/01/08

Page 2: 10080分でPythonからIP Messeneger

2

WHO ARE YOU?

DBエンジニアですノンプログラマPostgreSQLOracle

Page 3: 10080分でPythonからIP Messeneger

3

IP Messeneger

http://ipmsg.org/

Page 4: 10080分でPythonからIP Messeneger

4

IP Messenger

●1996年くらいからある?●LAN内でメッセージを投げ合うツール●国産●インフラ系の会社では結構みかける?

Page 5: 10080分でPythonからIP Messeneger

5

あらすじ:なんかタスク終わったら自動で担当者にIPMSGで通知して欲しいって言われてやってみたら、送信エラーがでなくて苦しんだので、結局自分で実装することになった話

Page 6: 10080分でPythonからIP Messeneger

6

Page 7: 10080分でPythonからIP Messeneger

7

だいたい2種類あった

●プロトコルをPurePythonで実装● ipmsg.exeをsubprocessで叩く

Page 8: 10080分でPythonからIP Messeneger

8

だいたい2種類あった

●プロトコルをPurePythonで実装● ipmsg.exeをsubprocessで叩く

試したが送信先がいなくてもエラーにならない

Page 9: 10080分でPythonからIP Messeneger

9

だいたい2種類あった

●プロトコルをPurePythonで実装● ipmsg.exeをsubprocessで叩く

こっち

Page 10: 10080分でPythonからIP Messeneger

10

https://github.com/shaung/ipmsg/

Page 11: 10080分でPythonからIP Messeneger

11

ipmsg(Pythonパッケージ)

●pipで入る!●試したら送れた!

Page 12: 10080分でPythonからIP Messeneger

12

ipmsg(Pythonパッケージ)

●pipで入る!●試したら送れた!● importしてから使うときのDocない…●そーすむずかしい...●結局送信エラーにならない...

Page 13: 10080分でPythonからIP Messeneger

13

そうだ自分で、つくろう

Page 14: 10080分でPythonからIP Messeneger

14

そうだ自分で、つくろう→1週間以上経過中

Page 15: 10080分でPythonからIP Messeneger

15

そうだ自分で、つくろう→1週間以上経過中7 * 24 * 60 = 10080

Page 16: 10080分でPythonからIP Messeneger

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

17

IP Messenegerのメッセージ以下6要素を:で連結して1行にした文字列で表現

● プロトコルバージョン● 1固定

● パケット番号● インクリメント

● 自分の名前● ホスト名● コマンド

● メッセージの属性(32bit)

● メッセージ● 本文とかその他パケットの追加情報

Page 18: 10080分でPythonからIP Messeneger

18

1:100:denzow:MyHost:8405280:こんにちは

Page 19: 10080分でPythonからIP Messeneger

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

20

$ ./send.py

嫌いな上司にめがけて

Page 21: 10080分でPythonからIP Messeneger

21

$ ./send.py

嫌いな上司にめがけて

Page 22: 10080分でPythonからIP Messeneger

22

Ψ(`▽´)Ψ

Page 23: 10080分でPythonからIP Messeneger

23

でも、上司がオフラインだったら?

Page 24: 10080分でPythonからIP Messeneger

24

でも、上司がオフラインだったら?

$ ./send.py$echo $?0

Page 25: 10080分でPythonからIP Messeneger

25

でも、上司がオフラインだったら?

$ ./send.py$echo $?0

失敗してても正常終了

Page 26: 10080分でPythonからIP Messeneger

26

(´・ω・`)

Page 27: 10080分でPythonからIP Messeneger

27

Why?

●そもそもUDP通信●受信完了のメッセージを相手が戻す規定になっていた

Page 28: 10080分でPythonからIP Messeneger

28

’・ω・

こんにちは with :IPMSG_SENDMSGIPMSG_SENDCHECKOPT

・_・`

とんでけー

Page 29: 10080分でPythonからIP Messeneger

29

’・ω・

こんにちは with :IPMSG_SENDMSGIPMSG_SENDCHECKOPT

・_・`

こんにちは with :IPMSG_SENDMSGIPMSG_SENDCHECKOPT

You got a mail(届いたかしら)

Page 30: 10080分でPythonからIP Messeneger

30

’・ω・

こんにちは with :IPMSG_SENDMSGIPMSG_SENDCHECKOPT

・_・`

こんにちは with :IPMSG_SENDMSGIPMSG_SENDCHECKOPT

IPMSG_RECVMSG

とりあえず応答おくるでー

(届いたかしら)

Page 31: 10080分でPythonからIP Messeneger

31

’・ω・

こんにちは with :IPMSG_SENDMSGIPMSG_SENDCHECKOPT

・_・`

こんにちは with :IPMSG_SENDMSGIPMSG_SENDCHECKOPT

IPMSG_RECVMSGIPMSG_RECVMSG

届いてた!

Page 32: 10080分でPythonからIP Messeneger

32

So..

●送りたいだけなのにリスニング必須●リスニングしつつ送信なのでスレッド?●送信済メッセージも管理必須

Page 33: 10080分でPythonからIP Messeneger

33

So..

●送りたいだけなのにリスニング必須●リスニングしつつ送信なのでスレッド?●送信済メッセージも管理必須●受け取ったメッセージのハンドラ必要● IPわからない場合は名前でおくりたい● import して普通に使えるようにしたい●などなど

Page 34: 10080分でPythonからIP Messeneger

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

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

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

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

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

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

40

よかったら

●GitHubにあげるだけあがってます● https://github.com/denzow/ipymessenger

●Docとコメントは週明けに日本語に変更● IPMSGは海外需要ない気がしてきたので…

●送信は実装済●受信は週明けに実装(希望)

Page 41: 10080分でPythonからIP Messeneger

41

つまり:なんかタスク終わったら自動で担当者にIPMSGで通知して欲しいって言われてやってみたら、送信エラーがでなくて苦しんだので、結局自分で実装することになった話

Page 42: 10080分でPythonからIP Messeneger

42

つまり:なんかタスク終わったら自動で担当者にIPMSGで通知して欲しいって言われてやってみたら、送信エラーがでなくて苦しんだので、結局自分で実装することになった話

人の、10080分が短縮できれば幸いです

Page 43: 10080分でPythonからIP Messeneger

43

ありがとうございました。