Mosh で Echo サーバー

実装中 の (mosh socket) ライブラリで Echo サーバーを書いてみました。
Echo サーバーとはクライアントから送られたものをそのまま、おうむ返しするサーバーです。
日本語も正しく送れます。

サーバー

見ての通り1つのクライアントにしか対応できません。fork しても良いのですがとりあえずシンプルに。

(import (rnrs)
        (mosh)
        (mosh socket))

(let ([server (make-server-socket "4649")])
  (display "Echo server: START\n")
  (let ([conn (socket-accept server)])
    (socket-close server)
    (let loop ([data (socket-recv conn 100 0)])
      (cond
       [(zero? (bytevector-length data))
        (socket-close conn)
        (display "Echo server: STOP\n")]
       [else
        (format #t "received ~s\n" (utf8->string data))
        (socket-send conn data 0)
        (loop (socket-recv conn 100 0))]))))

クライアント

(import (rnrs)
        (mosh)
        (mosh socket))

(let ([socket (make-client-socket "127.0.0.1" "4649")])
  (display "Echo client: write message and hit Enter key\n")
  (let loop ([line (get-line (current-input-port))])
    (cond
     [(eof-object? line) '()]
     [else
      (socket-send socket (string->utf8 line) 0)
      (format #t "Reply from Server: ~a\n" (utf8->string (socket-recv socket 100 0)))
      (loop (get-line (current-input-port)))])
    (socket-close socket)))

迷い

基本的に id:fujita-y さんの Ypsilon のライブラリに仕様を合わせています。(先行実装に感謝!)
迷っているのが socket-recv の戻り値。
Ypsilon は recv(2) の戻り値が 0 のときには Scheme 側には eof-object が返す。


ただし色々見て回ると

  • SOCK_STREAM (例:tcp) は recv の戻り値 0 イコール 終端
  • SOCK_DGRAM (例:udp) の場合は終端とは限らない

となっていて SOCK_DGRAM の場合が微妙かも。

ネットワークプログラミングに詳しくないので検討はずれの事を言っているかもしれないですが、もしこの辺りご存知の方がいれば教えていただけると助かります。