Androidでバックグランド処理を行うための手法がいくつかあるのでまとめてみた。
Showing posts with label プログラミング. Show all posts
Showing posts with label プログラミング. Show all posts
Tuesday, October 18, 2011
Tuesday, September 15, 2009
iconv_mime_decode on Ruby
PHPには iconv_mime_decode()という便利な関数がある。
さすがはPHP.
というわけで、Rubyでも同じような関数がほしかったのでテキトーに実装してみる。
PHPの中は見てないのでどうなってるのか知らない。
さすがはPHP.
というわけで、Rubyでも同じような関数がほしかったのでテキトーに実装してみる。
PHPの中は見てないのでどうなってるのか知らない。
def iconv_mime_decode( input, out_charset = 'utf-8' )こんなんでいいかなぁ。
while input.sub!(/(=\?[A-Za-z0-9-]+\?[BQbq]\?[^\?]+\?=)(?:(?:\r\n)?[\s\t])+(=\?[A-Za-z0-9-]+\?[BQbq]\?[^\?]+\?=)/, '\1\2')
end
begin
ret = input.sub!( /=\?([A-Za-z0-9-]+)\?([BQbq])\?([^\?]+)\?=/ ) {
charset = $1
enc = $2.upcase
word = $3
word = word.unpack({ "B"=>"m*", "Q"=>"M*" }[enc]).first
Iconv.conv( out_charset, charset, word )
}
return ret ? iconv_mime_decode( input, out_charset ) : input
rescue
# "Error while converting MIME string."
return input
end
end
Thursday, February 7, 2008
Is UHP really required?
そもそも、プロトコルを全部UDPでやれば、初期接続がクライアントからであるかぎり、UHPなんて考えなくてもいいのではなかろうか。
再送とかのチェックがめんどうではあるけども、それはデータ転送においても同じわけで。
まぁUHPつかえないルータの場合の考慮はどうすんだという問題もあるが、そのへんは要件次第か。
再送とかのチェックがめんどうではあるけども、それはデータ転送においても同じわけで。
まぁUHPつかえないルータの場合の考慮はどうすんだという問題もあるが、そのへんは要件次第か。
Wednesday, February 6, 2008
UDP Hole Punching その2
どうやら昨日書いた手法は特許とられてるらしい。ひどい話である。
・TCPでなんらかのデータ送信の後、UDPで補足データを送信する
という請求事項にひっかかるのだとか。(特許公開番号:2007-502585)
まぁいろいろ考えたが、最初のTCPによるセッション初期化をUDPでやっちまえばいい気がしてきたので、次のように変更。
まぁいいんでないかなあ。初期化失敗したら知らんぷり or TCPで続ける。
あとUHPを行う場合、クライアントのUDPソースポートも固定(bind())しておかないといつのまにか通信できなくなる可能性があるので注意すべき。
あとほんとに目的のサーバから送られてきたかどうかのチェックとか。
・TCPでなんらかのデータ送信の後、UDPで補足データを送信する
という請求事項にひっかかるのだとか。(特許公開番号:2007-502585)
まぁいろいろ考えたが、最初のTCPによるセッション初期化をUDPでやっちまえばいい気がしてきたので、次のように変更。
1. C UDP::UHPInitialize -- NOP
2. S UDP::UHPInitializeOK -- SESSIONID < UNIQUE ID >
3. C TCP::UHPComplete -- FLAG < 0(FAIL) | 1(SUCCESS) >[, SESSIONID < UNIQUE ID > ]
4. S TCP::UHPCompleteOK -- NOP
まぁいいんでないかなあ。初期化失敗したら知らんぷり or TCPで続ける。
あとUHPを行う場合、クライアントのUDPソースポートも固定(bind())しておかないといつのまにか通信できなくなる可能性があるので注意すべき。
あとほんとに目的のサーバから送られてきたかどうかのチェックとか。
Tuesday, February 5, 2008
UDP Hole Punching
仕事でUDPのデータストリームを扱っていて、さらにクライアントはNAT超えを考慮しなくてはならないということで、UDPのNAT超えでよく使われる手法、UDP Hole Punching (UHP) というものを実装することになった。
UDP Hole Punchingというのはルータに動的に空けられたNATテーブルの穴を逆から叩くことにより、NATの中のクライアントとUDP通信を可能にする技術であるからして。
さて、TCPのコントロールコネクションはもともとあるので、そのプロトコル上に UHP のネゴシエーションを付け加える形にした。
3と4で UDP Hole Punching を行うわけだが、UDPなのでロストするかもしれない。なので両者とも数回再送を試みる。
最終的に、クライアントが4の UHPRequestOK を受け取る事ができればUHPは成功であり、
5 の UHPComplete で SUCCESS を返すわけである。
3もしくは4をロストしたり、そもそも UHP が不可能な NAT 環境であった場合、FAILEDを返すことにより TCP へ Fallback するなりなんなりするようにする。といった寸法である。
以上のシーケンスをRubyでテストコード書いて(仕事のコードなので公開はできないが)実行してみたのだが、うまくいかない。
NAT なしの LAN内であれば動くのでアルゴリズム的な部分は間違ってない(と、思う)。
ルータが特殊なのかと思っていたのだが、帰宅途中で罠に気がついた。
実は、テストしているサーバは複数の Network Interface をもっている。
アドレスがプライベートで NAT の中にある eth0 と、実験でつかっている(つもり)のグローバルアドレスを持つ eth1 であり、default route は eth0 の NATルータである。
そして、サーバでudp socketがbind() しているアドレスは '0.0.0.0' である。
つまり、クライアントがグローバルアドレスに sendto()し、サーバが recvfrom() により取得したした client socket address へ sendto() を返す場合、サーバの source addres はカーネルが勝手に決めているのであり、基本的に default routeが使われるわけだから、eth0のプライベートアドレスになってしまう。
要するにサーバもNAT内あるものとして動作をしていた、というわけなのである。
UHP は NAT(client)からNAT(server) では仲介サーバが居ない限り不可能である。
今回はそういったケースは考慮しないので、素直にサーバの bind address をグローバルなものにして再実験をしたところ、うまく動作した。
教訓。udp socket を '0.0.0.0' に bind()してlistenするときは複数の interface や routing がないか注意しよう。
UDP Hole Punchingというのはルータに動的に空けられたNATテーブルの穴を逆から叩くことにより、NATの中のクライアントとUDP通信を可能にする技術であるからして。
さて、TCPのコントロールコネクションはもともとあるので、そのプロトコル上に UHP のネゴシエーションを付け加える形にした。
1. TCP C: UHPInitialize <NOP>
2. TCP S: UHPInitializeOK <SESSION ID> <SERVER UDP PORT>
3. UDP C: UHPRequest <SESSION ID>
4. UDP S: UHPRequestOK <NOP>
5. TCP C: UHPComplete <SUCCESS | FAILED>
6. TCP S: UHPCompleteOK <NOP>
3と4で UDP Hole Punching を行うわけだが、UDPなのでロストするかもしれない。なので両者とも数回再送を試みる。
最終的に、クライアントが4の UHPRequestOK を受け取る事ができればUHPは成功であり、
5 の UHPComplete で SUCCESS を返すわけである。
3もしくは4をロストしたり、そもそも UHP が不可能な NAT 環境であった場合、FAILEDを返すことにより TCP へ Fallback するなりなんなりするようにする。といった寸法である。
以上のシーケンスをRubyでテストコード書いて(仕事のコードなので公開はできないが)実行してみたのだが、うまくいかない。
NAT なしの LAN内であれば動くのでアルゴリズム的な部分は間違ってない(と、思う)。
ルータが特殊なのかと思っていたのだが、帰宅途中で罠に気がついた。
実は、テストしているサーバは複数の Network Interface をもっている。
アドレスがプライベートで NAT の中にある eth0 と、実験でつかっている(つもり)のグローバルアドレスを持つ eth1 であり、default route は eth0 の NATルータである。
そして、サーバでudp socketがbind() しているアドレスは '0.0.0.0' である。
つまり、クライアントがグローバルアドレスに sendto()し、サーバが recvfrom() により取得したした client socket address へ sendto() を返す場合、サーバの source addres はカーネルが勝手に決めているのであり、基本的に default routeが使われるわけだから、eth0のプライベートアドレスになってしまう。
要するにサーバもNAT内あるものとして動作をしていた、というわけなのである。
UHP は NAT(client)からNAT(server) では仲介サーバが居ない限り不可能である。
今回はそういったケースは考慮しないので、素直にサーバの bind address をグローバルなものにして再実験をしたところ、うまく動作した。
教訓。udp socket を '0.0.0.0' に bind()してlistenするときは複数の interface や routing がないか注意しよう。
Subscribe to:
Posts (Atom)