奥さんとのコミュニケーションにはfacebookチャットを活用しています。メールはやりとりの速度が遅い、SMSとかは特定の環境に依存している。というわけで、ブラウザからも使えるし各種専用クライアントもあるようなインフラを採用。以前はGoogleトークを使っていたのですが、最近Facebookチャットに移行。
facebookチャットはXMPPを利用しているので、XMPP対応しているメッセンジャーアプリならだいたい利用できます。まあ色々あるわけですけど
こんな感じのものを使っています。経路が多いし検索とかもウェブからサクッとできるので便利です。
XMPPから使うとグループチャットが扱えない(もしかしたら使えるのかもしれないけど知らない)のだけがちょっと不便なところかな。もうメールなんてシステム捨てましょう。
hogelog/simple-kestrel-client - GitHub
spymemcachedはKestrelで扱うとなんかどうもうまくない。xmemcachedはKestrel対応もしているとは書いてあるけど、なんだかどうもやっぱりpeekとかtimeoutとかを設定するとちゃんと動かない。とりあえず適当に書きなぐってみた。deleteとか他にも色々書いてないし色々適当。
こんな感じ。普通に使える。memcachedクライアントをkestrelクライアントとして使うのは悪手なのかなー。
public class SimpleKestrelClientTest { @Test public void set_peek_get_peektimeout_gettimeout() throws Exception { Socket socket = new Socket("127.0.0.1", 22133); SimpleKestrelClient client = new SimpleKestrelClient(socket); client.set("hoge", "hoge\r\nhoge"); assertThat(client.peek("hoge"), is("hoge\r\nhoge")); assertThat(client.get("hoge"), is("hoge\r\nhoge")); assertThat(client.get("hoge"), is(nullValue())); new Thread(){ @Override public void run() { try { Socket socket = new Socket("127.0.0.1", 22133); SimpleKestrelClient client = new SimpleKestrelClient(socket); Thread.sleep(1000); client.set("hoge", "hogefuga"); Thread.sleep(1000); client.set("hoge", "hogemoge"); } catch (Exception e) { e.printStackTrace(); } } }.start(); assertThat(client.peek("hoge", 5000), is("hogefuga")); assertThat(client.get("hoge"), is("hogefuga")); assertThat(client.get("hoge"), is(nullValue())); assertThat(client.get("hoge", 5000), is("hogemoge")); } }
割とわけのわからない挙動をする。
@Test
public void xmemcached_set_peek_get_peektimeout_gettimeout() throws Exception {
final XMemcachedClientBuilder builder = new XMemcachedClientBuilder(AddrUtil.getAddresses("127.0.0.1:22133"));
builder.setCommandFactory(new KestrelCommandFactory());
SerializingTranscoder transcoder = new SerializingTranscoder();
transcoder.setCharset("UTF-8");
builder.setTranscoder(transcoder);
final MemcachedClient client = builder.build();
client.setOpTimeout(5000);
client.set("moge", 0, "aaaaa");
client.set("hoge", 0, "hoge\r\nhoge");
assertThat(String.class.cast(client.get("hoge/peek")), is("hoge\r\nhoge"));
assertThat(String.class.cast(client.get("hoge")), is("hoge\r\nhoge"));
assertThat(String.class.cast(client.get("hoge")), is(nullValue()));
new Thread(){
@Override
public void run() {
try {
Thread.sleep(1000);
client.set("hoge", 0, "hogefuga");
Thread.sleep(1000);
client.get("moge/peek");
client.set("hoge", 0, "hogemoge");
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
assertThat(String.class.cast(client.get("hoge/peek/t=5000")), is("hogefuga"));
assertThat(String.class.cast(client.get("hoge")), is("hogefuga"));
assertThat(String.class.cast(client.get("hoge")), is(nullValue()));
assertThat(String.class.cast(client.get("hoge/t=5000")), is("hogemoge")); // 何故かこここでmogeにセットした"aaaaa"という文字列が得られる
}
追う気もしないので適当に自前で書いてみましたとさ。
WSH経由で起動して表示させないようにするのが楽。ddms.batに限らない。
ddms.jsなどとしてスタートメニューなりなんなり適当なところに置いてこのスクリプト経由で起動すると良い。
var shell = WScript.CreateObject("WScript.Shell"); shell.Run("C:/Android/android-sdk/tools/ddms.bat", 0);
当然だがddms.batの場所はインストール先により変わる。
なんかWicket ( http://wicket.apache.org/ ) がお手軽ウェブフレームワークらしいので触ってみることにしました。ついでにdotCloudとかいう最近有名なアレの上に乗っけてみることにしました。
http://docs.dotcloud.com/firststeps/install/ 参考に適当に
$ pip install dotcloud $ dotcloud setup
プロジェクトはmavenで作成します。しかしmavenのプロジェクト作成コマンドはいつもいつもめんどくさくて覚えてられないですね。Wicketさんはその辺のフォローもしっかりしています。Apache Wicket - Create a Wicket Quickstartで作りたいプロジェクトのグループIDとアーティファクトIDを入力すれば実行すべきコマンドが出てきます。
$ mvn archetype:generate -DarchetypeGroupId=org.apache.wicket -DarchetypeArtifactId=wicket-archetype-quickstart -DarchetypeVersion=1.5.3 -DgroupId=org.hogel -DartifactId=wicket-test -DarchetypeRepository=https://repository.apache.org/ -DinteractiveMode=false [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building Maven Stub Project (No POM) 1 [INFO] ------------------------------------------------------------------------ [INFO] [INFO] >>> maven-archetype-plugin:2.0:generate (default-cli) @ standalone-pom >>> [INFO] [INFO] <<< maven-archetype-plugin:2.0:generate (default-cli) @ standalone-pom <<< [INFO] [INFO] --- maven-archetype-plugin:2.0:generate (default-cli) @ standalone-pom --- [INFO] Generating project in Batch mode [INFO] Archetype defined by properties [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1.547s [INFO] Finished at: Sat Jan 07 22:58:38 JST 2012 [INFO] Final Memory: 7M/133M [INFO] ------------------------------------------------------------------------
簡単にできました。
$ cd wicket-test $ mvn jetty:run [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building quickstart 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ いろいろたくさん... INFO - WebApplication - [wicket.wicket-test] Started Wicket version 1.5.3 in DEVELOPMENT mode ******************************************************************** *** WARNING: Wicket is running in DEVELOPMENT mode. *** *** ^^^^^^^^^^^ *** *** Do NOT deploy to your live server(s) without changing this. *** *** See Application#getConfigurationType() for more information. *** ******************************************************************** 2012-01-07 22:59:56.017:INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:8080 STARTING 2012-01-07 22:59:56.376:INFO:oejs.AbstractConnector:Started SslSocketConnector@0.0.0.0:8443 STARTING [INFO] Started Jetty Server
起動しました。アクセスしてみましょう→ http://localhost:8080/
コマンド叩いただけなのになんかできてて最近のウェブフレームワークっぽいですね。中身はあとで触っていきましょう。
mvn jetty:runしたときにこんな表示をしていましたね。
INFO - WebApplication - [wicket.wicket-test] Started Wicket version 1.5.3 in DEVELOPMENT mode ******************************************************************** *** WARNING: Wicket is running in DEVELOPMENT mode. *** *** ^^^^^^^^^^^ *** *** Do NOT deploy to your live server(s) without changing this. *** *** See Application#getConfigurationType() for more information. *** ********************************************************************
上記メッセージの通り、WicketApplication.javaにWicketApplication#getConfigurationType()を追加します。
package org.hogel; import org.apache.wicket.RuntimeConfigurationType; import org.apache.wicket.protocol.http.WebApplication; /** * Application object for your web application. If you want to run this application without deploying, run the Start class. * * @see org.hogel.Start#main(String[]) */ public class WicketApplication extends WebApplication { /** * @see org.apache.wicket.Application#getHomePage() */ @Override public Class<HomePage> getHomePage() { return HomePage.class; } /** * @see org.apache.wicket.Application#init() */ @Override public void init() { super.init(); // add your configuration here } @Override public RuntimeConfigurationType getConfigurationType() { return RuntimeConfigurationType.DEPLOYMENT; } }
mavenでWicketプロジェクトをwarファイルにパッケージング。
$ mvn package [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building quickstart 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] 色々...
wicket-test/target/wicket-test-1.0-SNAPSHOT.warができている。おしまい。
DotCloud Documentationを参考に先のwarファイルをデプロイしてみる。
dotCloud上にwickettestというアプリケーションを作成する。
$ dotcloud create wickettest Created application "wickettest"
dotcloudディレクトリを作ってdotcloud用のファイルをまとめる。
$ mkdir dotcloud $ cp target/wicket-test-1.0-SNAPSHOT.war dotcloud/ROOT.war
dotcloud/dotcloud.ymlに以下の内容を記述
www: type: java
デプロイ。
$ dotcloud push wickettest dotcloud
http://wickettest-hogelog.dotcloud.com/
デプロイ完了。うーん便利な時代ですねー。
とりあえずベタベタにチャット的なものを。
ソースコードは https://github.com/hogelog/chatty に。
Windowsで動くWebSocketサーバをサクッと書くにはJavaでJetty使うのが一番楽だなあということがよくわかりました。rubyのアレとかpythonのソレとかこれとか、だいたいlibeventやらなんらかのネイティブライブラリを使っているので面倒。JettyでWebSocket使うには、pom.xmlを適当に仕上げて*1、ソース書いて、あとは
$ mvn jetty:run
と叩くだけで依存するライブラリ落としてきて(ネイティブライブラリのビルドとかが始まることなしに)普通にサーバが動き始める。良い。
pom.xmlにjetty-websocketを記述。
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-websocket</artifactId>
<version>8.1.0.RC1</version>
</dependency>
@WebServlet("/chatty") public class ChattyServlet extends WebSocketServlet { public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) { return new ChattyWebSocket(); } }
public class ChattyWebSocket implements WebSocket.OnTextMessage { public void onOpen(Connection connection); public void onClose(int closeCode, String message); public void onMessage(String data); }
こんな感じで書く。WebSocket.OnTextMessage以外にもOnBinaryMessageとかもあるし普通に使いやすそう。
http://download.eclipse.org/jetty/stable-8/apidocs/org/eclipse/jetty/websocket/WebSocket.html
*1:それが面倒なんだろうけど