Socket and Port

GaucheのネットワークモジュールがWindowsMeでまともに動かない。調べてみるとsocket-input-portかsocket-output-portを呼ぶ箇所で落ちる。内部で_open_osfhandleを使っているのだが、この関数はWin9x系では常に-1を返すのである。_open_osfhandleを簡単に説明すると、ソケットからファイルハンドルを得る関数である。つまり、ソケットが接続された先をファイルと同じように扱える仕組みというわけだ。こういう透過的な仕組みがOSレベルで提供されているのはとても有難いことではあるのだけれど、Win9x系で動かないというのが致命的である。
仕方がないのでsocket-input-port,socket-output-portに相当する関数を書いた。途中で本家のWikiで助言をもらったりしながらではあるけどなんとか一応は使えるものになった。つまらない質問にも親切に助言をくれた川合氏に感謝。net.scmにこれを入れておけばrfc.httpといった上位のモジュールも使えてる。効率は悪いし、不格好なので使いながら練りこんでいくつもり。

(use gauche.net)
(use gauche.vport)
(use gauche.uvector)


(define (socket-output-port socket)
  (let ((putb (lambda(ch)
		(if (integer? ch) (set! ch (integer->char ch)))
		(socket-send socket (string ch))))
	(puts (lambda(str)
		(socket-send socket str))))
    (make <virtual-output-port>
      :putb putb :puts puts)))

(define (socket-input-port socket)
  (let ((getb (lambda()
		(let ((str (socket-recv socket 1)))
		  (if (and (string? str)
			   (not (zero? (string-length str))))
		      (string-byte-ref str 0)
		      #f))))
	(gets (lambda(siz)
		(socket-recv socket siz))))
    (make <virtual-input-port>
      :getb getb :gets gets)))