EmacsでEcho Serverを作る例( http://www.emacswiki.org/emacs/EmacsEchoServer )
があったので逆にクライアントを作ってみた。
きっとこの程度の例ならどっかに残ってるとは思うけど練習。
Echo Clientをつくるだけなのもアレなので簡易fetchを作ってみた。
ホスト名と取得するパスを指定してHTTPで簡易的に取ってくる。
(defvar myfetch-name "myfetch")
(defvar myfetch-buffer-name "*myfetch output*")
(defvar myfetch-buffer nil)
(defun myfetch (host file)
(interactive "sHost: \nsFile: ")
(unless (process-status myfetch-name)
(setq myfetch-buffer (get-buffer-create myfetch-buffer-name))
(let ((proc (make-network-process :name myfetch-name
:buffer myfetch-buffer
:family 'ipv4
:host host
:service 80
:sentinel 'myfetch-sentinel
:nowait nil
:filter 'myfetch-filter :server nil)))
(myfetch-logging
(format "Access to http://%s:80/%s" host file))
(myfetch-logging "Make connection...")
(process-send-string
proc (format "GET /%s HTTP/1.0\r\n\r\n" file)))))
(defun myfetch-filter (proc string)
(myfetch-logging string))
(defun myfetch-sentinel (proc msg)
(myfetch-logging (format "sentinel: proc=%s msg=%s" proc msg)))
(defun myfetch-logging (string)
(when (get-buffer myfetch-buffer)
(with-current-buffer myfetch-buffer
(goto-char (point-max))
(insert (current-time-string)
" " string)
(newline))))
localhostのApacheにアクセスした結果は以下の通り。
おぉちゃんと返ってきてる。
Mon May 20 00:24:39 2013 Access to http://localhost:80/index.html
Mon May 20 00:24:39 2013 Make connection...
Mon May 20 00:24:41 2013 HTTP/1.1 200 OK
Date: Sun, 19 May 2013 15:24:40 GMT
Server: Apache/1.3.41 (Darwin) PHP/4.4.9 mod_perl/1.29 mod_ssl/2.8.31 OpenSSL/0.9.7l
Content-Location: index.html.en
Vary: negotiate,accept-language,accept-charset
TCN: choice
Last-Modified: Fri, 04 May 2001 00:00:38 GMT
ETag: "39216-5b0-3af1f126;4d11e7c5"
Accept-Ranges: bytes
Content-Length: 1456
Connection: close
Content-Type: text/html
Content-Language: en
Expires: Sun, 19 May 2013 15:24:40 GMT
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
...中略...
</body>
</html>
Mon May 20 00:24:41 2013 sentinel: proc=myfetch msg=connection broken by remote peer
例の流れ
-
make-network-process
で通信するプロセスを作成 -
process-send-string
で送信 - 受信はfilter(コールバック関数、例では
myfetch-filter
)で処理
番兵(sentinel)は、何かプロセスに変化が起きたとき(死んだときとか)に呼ばれるコールバック関数
終了処理
delete-process
ってのがある。これはプロセスを殺して直ちに忘れてしまう。実際、例のmyfetch-filterの最後にこいつを挟んでみたところちょっと長いページだと途中で切れた。まあ当たり前か。
今回は、サーバから切断してくれるけど何もしなくて良いのかな?番兵は切断を関知しているっぽいけど。
make-network-processとopen-network-stream
手元にあった通信してそうなemacs lispを斜め読みしていたら通信を始める手続きとして
make-network-process
と open-network-stream
の2種類があった。
なお、 make-network-process
の方はEmacs 22以上のみらしい。
(実際mewのソースには前者が使えなかったら後者を使うようです。)
make-network-process
は open-network-stream
よりも低レベルなネットワークを扱えるらしい。
make-network-processについてもう少し深く
ほとんどマニュアルの訳になってますケド…
ネットワークコネクションを作成、もしくは、サーバを作成する手続き。戻り
値はプロセスオブジェクト。引数はkeyword/argumentリスト
keyword | description |
---|---|
:name | プロセスに使用する名前。ユニーク |
:buffer | プロセスの出力をするバッファ。nilも可。 |
:host | ホスト名。文字列かlocalhostを表すシンボル 'local |
:service | クライアントではつなぐ先のポート番号。サーバではlistenするポート番号。tを指定すると適当に選ばれる |
:type | nil (stream; default) / datagram ? |
:family | local / ipv4 / ipv6 |
:nowait | BOOL ストリーム通信においてnon-nilを指定するとnon-blockingになる |
:filter | フィルタ関数 |
:sentinel | 番兵関数 |
後半から適当だし説明してないオプション沢山あるけどよく分からないのでパス
参考
- Network - GNU Emacs Lisp Reference Manual
- Network Processes - GNU Emacs Lisp Reference Manual
- EmacsWiki: Emacs Echo Server