Born Neet
node.websocket.jsで超適当ホワイトボードアプリ
- 2010-01-31 (Sun)
- html5
今週は仕事とドラクエVIが忙しくて全然勉強の時間がとれませんでした。
(モンスターが仲間に入らないのと難易度が下がってるのにはがっかりしましたが、やっぱり6はいいですね。)
というわけで週末、しかも2日目に慌ててやってみます。
触るのは、引き続きWeb Socket(s)。
前回のでAPI(クライアントサイド。つまりJS。sがつく方)は何となくイメージできたかなぁという感じ。
しかし、プロトコル(Web Socket protocol。こっちはsがつかない)はイマイチ理解できてません。
こういう時はやっぱり手を動かすのが一番ということでとりあえず何か作ってみます。
※ ほんとはパケットキャプチャ取りたかったんですがうまくいかなかったので断念
それでは始めましょう。
まずは参考記事探しから。
Web Socket ProtocolのRFC和訳 - YAMAGUCHI::weblog
ないと思ってたプロトコルの日本語訳がありました。感謝です。
ただこの仕様短いのはいいんだけど、細かい説明が全然ない・・・。
websoket-protcol:ヘッダって何の意味があるんだー。
(node.websokcet.jsではまだ未実装って書いてあるし)
InfoQ: HTML 5 Web Sockets vs. Comet and Ajax
仕様のこととかは詳しく書いてませんがおもしろかったです。
PubSubHubbubとWebSocketsとクライアントサイドのjavascript « ku
こちらも他の実現方法との比較。読みやすいです。
Html5 Web Applications
Html5, Web Applications 2
HTML5のWebアプリ関連仕様をサクっとまとめた素晴らしいプレゼンです。
[追記(2010/1/31 14:15)]
おっと、忘れてた。
HTTP/1.1 から TLS へのアップグレード
Upgrade
HTTPのUpgradeについて。さっぱりわからん。
[/追記]
やっぱまだ日本語のソースは少ないですねぇ。
ネットサーフィンはこれぐらいにして、
うーん・・・Cometアプリの代表例ホワイトボードでも作ってみますか。
というわけで、できたのがこちら。
ソースはいつも通りご自由に。
説明はコメントで。そんな難しいことはやってません。
(セキュリティ0なので間違っても公開しないで下さいね)
うーん、一応思った通りに動いたけど、サーバ側でsetIntervalやるのは綺麗じゃないなー。
このコード量、しかもJSだけでこういうアプリが作れるのはちょっとした衝撃でした。
サーバ(node.websocket.js/modules/wb.js)
var Module = this.Module = function(){
// グローバルにしとくと楽
sys = require('sys');
};
Module.prototype.onData = function(data, connection) {
// 初期化
if (data == 'start'){
// 定期的にファイルをcatして変わってたらクライアントに送る
this.interval = setInterval(function(){
var self = this;
sys.exec('cat temp').addCallback(function(stdout, stderr) {
if (self.temp != stdout) {
connection.send(stdout);
}
self.temp = stdout;
});
}, 100);
}
// データを受信したらtempファイルに書き込む(超脆弱!!)
else {
sys.exec('echo "' + data +'" > temp');
}
};
// 後始末
Module.prototype.onDisconnect = function(connection){
clearInterval(this.interval);
};
クライアント(apache/htdocls/wb.html)
<!doctype html>
<html>
<head>
<title>whiteboard demo</title>
<style>
canvas {
border: 1px solid black;
position: relative;
}
</style>
</head>
<body>
<h1>whiteboard demo</h1>
<canvas width="300" height="200"></canvas><br />
<input type="button" value="clear" />
<script>
// node.websocket.js/modules/wb.jsに繋ぐ
var webSocket = new WebSocket('ws://localhost:8000/wb');
/* お絵かき処理ここから */
var canvas = document.getElementsByTagName('canvas')[0];
var ctx = canvas.getContext('2d');
var isDraw = false;
var x, y;
canvas.addEventListener('mousedown', function(e) {
ctx.moveTo(x, y);
isDraw = true;
}, 'false');
canvas.addEventListener('mousemove', function(e) {
x = e.layerX;
y = e.layerY;
if (isDraw) {
ctx.lineTo(x, y);
ctx.stroke();
}
}, 'false');
canvas.addEventListener('mouseup', function(e) {
isDraw = false;
webSocket.send(canvas.toDataURL());
}, 'false');
/* お絵かき処理ここまで */
// サーバ側に初期化を知らせる
webSocket.onopen = function(event){
webSocket.send('start');
};
// データ受信時は問答無用でcanvasを更新
webSocket.onmessage = function(event){
var img = new Image();
img.onload = function() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0);
};
img.src = event.data;
};
// 白紙に戻す
document.querySelector('input[value=clear]').addEventListener('click', function() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
webSocket.send(canvas.toDataURL());
}, 'false');
</script>
</body>
</html>
HTML5に追いつこう!Pure JSでWeb Socketsを動かしてみる
- 2010-01-25 (Mon)
- html5
HTML5の仕様も、コミュニティの皆さんも動きが速すぎてすっかり置いてかれています。
とはいえ、HTML5は勉強しておいて絶対損はないはずなので、
マイペースで頑張りたいと思います。。
そんな中、今日、
噂のnode.websocket.jsでサーバサイドJSとHTML5 WebSocketを体験してみたの巻 - ダウンロードたけし(寅年)の日記
Real time online activity monitor example with node.js and WebSocket @ Bamboo Blog
なんていう素敵な記事を見つけました。
Apacheは好きだけどPythonはちょっと・・・な僕でもこれならできるはず!と
初めてのWeb Socketsに挑戦してみました。
というわけで、改めてお勉強。
まずはAPI仕様。(プロトコルは長いし英語なのでまた今度)
W3C - 『The Web Sockets API』日本語訳 - HTML5.JP
うん、これだけじゃわからんですね^^
デモとか見て勉強しよう。
こてさきAjax:apache+mod_pywebsocetを用いたliteなwebsocketsチャットサンプル - livedoor Blog(ブログ)
pywebsocketの例。サーバサイドの処理の説明がわかりやすいです。
こてさきAjax:apache + web sockets (pywebsocket) tips #0 - livedoor Blog(ブログ)
こてさきAjax:lite websocket チャットサンプルを更新しました。 - livedoor Blog(ブログ)
引き続きpywebsocket。
Origin checkとHeartBeatがキーワードというかいつかハマリそうな予感。
覚えておこう。
こてさきAjax:websocketでは、encodeURIComponet()は使うべきではない - livedoor Blog(ブログ)
データはUTF-8で送受信するので、encodeURI()しなくても良いと、ふむふむ。
なんとなくイメージが湧いてきた。
プレゼン資料とかも漁ってみる。
(やっぱシーケンスがあるとわかりやすいですね!)
WebSocketでリアルタイムWeb
かなり噛み砕いた説明でわかりやすいです。
100113_opera webkit勉強会(websocket)
こてさきAjax:websocket関連の説明png - livedoor Blog(ブログ)
図がいっぱい。素敵。
【特集】詳解! HTML 5と関連APIの最新動向 - Webアプリ開発編 (10) Web Sockets | エンタープライズ | マイコミジャーナル
Kaazingを使ったデモ。初心者を切り捨てない感じで助かります。
そろそろ良いかな…よし、やってみよう!
node.jsのインストール
node.jsのサイトからnode-v0.1.26.tar.gzをダウンロード。
cd node-v0.1.26/
./configure —prefix=/Users/t/node.js/
※ prefix指定はできない?
./configure
※ 諦めてそのままインストールする。
make
sudo make install
which node
/usr/local/bin/node
何事もなく終了。
※ ホントはユーザ権限でインストールしたかったけど・・・
Hello, node.js
とりあえず、指定ディレクトリをlsして返すプログラムを書いてみました。
queryから取ろうと思ったけど、うまく動かないメソッドとかもあったのでやめときました。
vi ls.js
var sys = require('sys');
var filename = process.ARGV[2];
var http = require("http");
http.createServer(function(req, res){
res.sendHeader(200,{"Content-Type": "text/html; charset=UTF-8"});
sys.exec('ls -alF ' + filename).addCallback(function _exec(stdout, stderr) {
res.sendBody(stdout);
res.finish();
});
}).listen(8000);
:wq
node ls.js .
[別ターミナルで]
telnet localhost 8000
GET / HTTP/1.1
host:localhost
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Transfer-Encoding: chunked
1cc
total 80
drwxr-xr-x 9 t staff 306 1 25 00:17 ./
drwxr-xr-x+ 47 t staff 1598 1 24 23:27 ../
-rw-r--r--@ 1 t staff 6148 1 25 00:17 .DS_Store
-rwxr-xr-x@ 1 t staff 304 1 24 23:42 example.js*
-rwxr-xr-x@ 1 t staff 329 1 24 23:49 log.txt*
-rwxr-xr-x@ 1 t staff 334 1 25 00:17 ls.js*
drwxr-xr-x@ 20 t staff 680 1 24 23:35 node-v0.1.26/
drwxr-xr-x 5 t staff 170 1 25 00:17 old/
-rwxr-xr-x@ 1 t staff 601 1 24 23:50 tail.js*
こんな感じで返ってきます。
Hello, Web Sockets
ようやく本題・・・ですが眠いので既存サンプルを動かすだけにしときます。
git clone git://github.com/Guille/node.websocket.js.git
node.websocket.js at masterをチェックアウト
cd node.websocket.js
cp test/test.html ~/apache/htdocs/
apache上にクライアントを配置
vi ~/apache/htdocs/test.html
var webSocket = new WebSocket('ws://localhost:8000/time');
ポートを8000に変更(apacheと競合してたので)
node runserver.js --port="8000"
Web Socketsサーバを起動
apachectl start
apacheを起動(8080を使ってます)
Google Chrome 4+からlocalhost:8080/test.htmlにアクセスすると、
時刻がリアルタイムで更新されるサンプルが表示されます。
(地味ですが確かにpullではなくpushで実現されています。)
まとめ
思っていたより手軽に触れそうです。
僕程度のスキルでも2時間程度で動かすとこまではできました。
さて、なんか面白いことできないかなー。
今更ながら、人工無脳なTwitterボット作ってみた
- 2010-01-24 (Sun)
- Perl
Perlの勉強の為、久々に人工無脳を作ってみました。
説教っぽく聞こえなくもない言葉を30分に1回つぶやきます。
迷言ボット (bornneet) on Twitter
興味のある方はfollowしてみて下さい。
精度は全然ですが、まぐれで良いこというかもしれませんよ^^
最初は、以下の記事を参考にNet::Twitterでやろうとしたのですが、
Macにうまくインストールできなかったので、断念。
Twitter ボットの作り方 Perl 編 (1) – OTCHY.NET
cpanをupdate(cpan > install Bundle::CPAN)とかやってみるも、状況変わらず。
(テクノロ散策: PerlでNet::Twitterがインストールできない時はcpanをアップデート)
xreaにはNet::Twitterが入ってるので、使いたかったんですが、
仕方なく生Perlで書くことにしました。
参考にしたのはこちらの3記事。
404 Blog Not Found:API - Twitterfeed から Hatena::Bookmark Web Hookへ
nDiki: Net::Twitter - Net::OAuth を使って Twitter からフィードを取得 (2009-12-30)
LWP::UserAgentで基本認証とPOSTを - 徒書
最後の最後、xreaでの動作確認でさらにはまりました。
Storableに「Byte order is not compatible at blib/lib/Storable.pm」と言われてもうお手上げ。
またまた先人の力をお借りして何とか解決しました。
(storeを使わず、nstoreを使用)
404 Blog Not Found:perl - 勝手に添削 - Storable
Perl 5.6.2→5.8.7移行メモ
いやぁ、相変わらず、Perlには慣れませんねぇ…orz
※ おまけでxrea無料版ではcronが動かせないという罠も。(何を今さら)
というわけでcore serverのアカウントで稼働させてます。
Firefox3.6がリリースされたので、canvas作品をFile API(とDrag&Drop)に対応させてみた
- 2010-01-22 (Fri)
- html5
お久しぶりです。
僕がインターネットのない生活を送っている間に、
待望のFirefox3.6がリリースされましたね!
これでFirefoxがターゲットのサイトなら、FireAPIを使い放題です!!
(今まではβ版だったので、開発者しか使ってませんでしたからね・・・)
というわけで、以下の2作品をFile API対応させときました。
ダイアログを使うか、選択欄にdrag&dropすればローカルファイルを指定できます。
錯覚エディター by HTML5 Canvas
canvasで画像拡大鏡
何かたまにおかしくなりますが、サンプルということで許して下さい^^
あと、巨大ファイルや画像じゃないファイルを指定すると壊れますのでご注意を。
File API、面白いので皆さん是非試してみて下さい!
※ 以前File APIの簡単な使い方をLTしたのでよろしければどうぞ。
htmlのキーワード一覧
- 2010-01-17 (Sun)
- html/css
htmlも。
HTML Elements Index – Jens Meiert
index of HTML5 elements
HTML5 Elements and Attributes
各HTMLバージョンのDOCTYPE宣言のサンプル集
最後の方、ちょっと投げました。
っていうかタグと属性識別すんの忘れた…orz
cssもプロパティとvalue一緒にしちゃったし…。
!--
!DOCTYPE
--
-//W3C//DTD HTML 4.01 Frameset//EN
-//W3C//DTD HTML 4.01 Transitional//EN
-//W3C//DTD HTML 4.01//EN
-//W3C//DTD XHTML 1.0 Frameset//EN
-//W3C//DTD XHTML 1.0 Strict//EN
-//W3C//DTD XHTML 1.0 Transitional//EN
-//W3C//DTD XHTML 1.1//EN
?xml
abbr
accept
accept-charset
access
accesskey
acronym
action
address
align
alink
alt
applet
archive
area
aria-
article
aside
audio
axis
background
base
basefont
bdo
bgcolor
big
blockcode
blockquote
body
border
br
button
canvas
caption
cellpadding
cellspacing
center
char
charoff
charset
checkbox
checked
cite
class
classid
clear
code
codebase
codetype
col
colgroup
color
cols
colspan
command
compact
content
contenteditable
contextmenu
coords
data
data-
datalist
date
datetime
datetime-local
dd
declare
defer
del
delete
details
dfn
di
dir
disabled
dispatch
div
dl
draggable
dt
em
email
embed
encoding
enctype
EUC-JP
ev:listener
face
fieldset
figure
file
font
footer
for
form
frame
frameborder
frameset
group
h1
h1, h2, h3, h4, h5, and h6
h2
h3
h4
h5
h6
handler
head
header
headers
height
hgroup
hidden
hr
href
hreflang
hspace
html
http-equiv
http://www.w3.org/1999/xhtml
http://www.w3.org/TR/html4/frameset.dtd
http://www.w3.org/TR/html4/loose.dtd">
http://www.w3.org/TR/html4/strict.dtd
http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd
http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd
http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd
id
iframe
image
img
input
ins
insert
isindex
ismap
itemid
itemprop
itemref
itemscope
itemtype
ja
kbd
keygen
label
lang
language
legend
li
link
listing
load
longdesc
map
marginheight
marginwidth
mark
marquee
maxlength
media
menu
message
meta
meter
method
model
month
multiple
name
nav
nl
noframes
nohref
noresize
noscript
noshade
nowrap
number
object
ol
onabort
onblur
oncanplay
oncanplaythrough
onchange
onclick
oncontextmenu
ondblclick
ondrag
ondragend
ondragenter
ondragleave
ondragover
ondragstart
ondrop
ondurationchange
onemptied
onended
onerror
onfocus
onformchange
onforminput
oninput
oninvalid
onkeydown
onkeypress
onkeyup
onload
onloadeddata
onloadedmetadata
onloadstart
onmousedown
onmousemove
onmouseout
onmouseover
onmouseup
onmousewheel
onpause
onplay
onplaying
onprogress
onratechange
onreadystatechange
onreset
onscroll
onseeked
onseeking
onselect
onshow
onstalled
onsubmit
onsuspend
ontimeupdate
onunload
onvolumechange
onwaiting
optgroup
option
output
param
password
plaintext
pre
profile
progress
prompt
PUBLIC
radio
range
rb
rbc
readonly
rebuild
recalculate
refresh
rel
repeat
reset
rev
revalidate
role
rows
rowspan
rp
rt
rtc
ruby
rules
samp
scheme
scope
script
scrolling
search
secret
section
select
select1
selected
send
separator
setfocus
setindex
setvalue
shape
Shift_JIS
size
small
source
span
spellcheck
src
standby
start
strike
strong
style
sub
sub and sup
submit
summary
sup
switch
tabindex
table
target
tbody
td
tel
text
textarea
tfoot
th
thead
time
title
tr
trigger
tt
type
ul
upload
url
usemap
UTF-8
valign
value
valuetype
var
version
video
vlink
vspace
week
width
xml:lang
xmlns
xmp
- Search
-
Loading
- Feeds
- Links
- スポンサードリンク