10080分でpythonからip messeneger

Post on 12-Jan-2017

1.466 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

1

10080分でPythonから

IP Messenger

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

2

WHO ARE YOU?

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

3

IP Messeneger

http://ipmsg.org/

4

IP Messenger

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

5

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

6

7

だいたい2種類あった

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

8

だいたい2種類あった

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

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

9

だいたい2種類あった

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

こっち

10

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

11

ipmsg(Pythonパッケージ)

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

12

ipmsg(Pythonパッケージ)

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

13

そうだ自分で、つくろう

14

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

15

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

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だし比較的シンプル

17

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

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

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

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

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

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

18

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

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))

投げるだけなら簡単

20

$ ./send.py

嫌いな上司にめがけて

21

$ ./send.py

嫌いな上司にめがけて

22

Ψ(`▽´)Ψ

23

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

24

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

$ ./send.py$echo $?0

25

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

$ ./send.py$echo $?0

失敗してても正常終了

26

(´・ω・`)

27

Why?

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

28

’・ω・

こんにちは with :IPMSG_SENDMSGIPMSG_SENDCHECKOPT

・_・`

とんでけー

29

’・ω・

こんにちは with :IPMSG_SENDMSGIPMSG_SENDCHECKOPT

・_・`

こんにちは with :IPMSG_SENDMSGIPMSG_SENDCHECKOPT

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

30

’・ω・

こんにちは with :IPMSG_SENDMSGIPMSG_SENDCHECKOPT

・_・`

こんにちは with :IPMSG_SENDMSGIPMSG_SENDCHECKOPT

IPMSG_RECVMSG

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

(届いたかしら)

31

’・ω・

こんにちは with :IPMSG_SENDMSGIPMSG_SENDCHECKOPT

・_・`

こんにちは with :IPMSG_SENDMSGIPMSG_SENDCHECKOPT

IPMSG_RECVMSGIPMSG_RECVMSG

届いてた!

32

So..

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

33

So..

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

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))

投げるだけなら簡単

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()

投げるだけなら簡単だったのに

サーバ処理のメインループだけで

これ

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して

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()

投げるだけなら簡単だったのに

パケットがきてたらパケットをメッセージにして

アクション

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で処理

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()

投げるだけなら簡単だったのに

送信ミスとかでキューに長くのこった

メッセージ等のクリーンアップ

40

よかったら

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

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

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

41

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

42

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

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

43

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

top related