ocaml-event(libevent ocaml wrapper)를 이용하여 echo server를 OCaml 언어로 작성해 봤습니다. libevent C API에 익숙해서 ocaml 답지 않게 짜진거 같은 느낌도 들지만 워낙 프로그램이 간단하다보니 크게 틀려질 부분은 없어보이는군요. 다른건 문제가 없었는데 Makefile에서 ocamlopt로 native 컴파일할때 C 라이브러리가 링크가 안되서 약간 헤맸고, printf 후에 flush stdout을 하는 부분이 있는데, stdout이 Unix 네임스페이스에 있는 stdout으로 인식이 되어 컴파일이 안되더군요. 그래서 Pervasives.stdout으로 지정하니 컴파일 잘되네요.

아래는 echo_server_event.ml 소스입니다.


(*
 * echo server using libevent
 *
 * Copyright (c) 2007 Chun-Koo Park
 * All rights reserved.
 *)


open Unix

let rec sock_write sock buf offset = function
  | 0 -> ()
  | len ->
      let nwritten = write sock buf offset len in
        sock_write sock buf (offset + nwritten) (len - nwritten)

let echo_callback event fd event_type =
  let buf = String.create 64 and nread = ref 1 in
    while !nread > 0 do
      nread := read fd buf 0 64;
      sock_write fd buf 0 !nread;
    done;
    if !nread > 0 then
      Libevent.add event None
    else
      Printf.printf "connection closed\n";
      flush Pervasives.stdout

let accept_callback event fd event_type =
  let asock, addr = accept fd in
  let evnew = Libevent.create () in

  Libevent.set evnew asock [Libevent.READ] false (echo_callback evnew);
  Libevent.add evnew None;

  Libevent.add event None

let tcp_server_sock port =
  let ssock = socket PF_INET SOCK_STREAM 0
  and addr = inet_addr_any in
    bind ssock (ADDR_INET (addr, port));
    setsockopt ssock SO_REUSEADDR true;
    listen ssock 5;
    ssock

let _ =
  let listenport = 2007 in
  let acceptfd = tcp_server_sock listenport in
  let acceptev = Libevent.create () in

  Libevent.set acceptev acceptfd [Libevent.READ] false (accept_callback acceptev);
  Libevent.add acceptev None;

  Libevent.dispatch ()
 


ocaml-event를 이용한 echo 서버와 thread와 fork로 짠 echo 서버의 Makefile입니다. ocaml findlib를 이용했습니다. ocaml findlib에 대해서 얼마전에 올린글을 참고하세요.


# Makefile
#
# Copyright (c) 2007 Chun-Koo Park
# All rights reserved.

OCAMLC=ocamlfind ocamlc
#OCAMLC=ocamlfind ocamlopt

EXEC=echo_server_fork echo_server_thread echo_server_event
all: $(EXEC)

echo_server_fork: echo_server_fork.ml
    $(OCAMLC) -o $@ -package unix -linkpkg $@.ml

echo_server_thread: echo_server_thread.ml
    $(OCAMLC) -o $@ -thread -package "threads unix" -linkpkg $@.ml

echo_server_event: echo_server_event.ml
    $(OCAMLC) -o $@ -package "libevent unix" -linkpkg $@.ml -ccopt -L/usr/local/lib -cclib -levent

clean:
    rm -f *.cmo *.cmi *.cmx *.o $(EXEC)

# vi:set noet:
 


thread 사용할때는 -thread 옵션을 주고, ocamlopt로 native 컴파일할 경우를 위해서 -cclib로 libevent C 라이브러리를 지정해주었습니다. -cclib event로 지정하면 라이브러리를 찾을거라 생각했는데 -cclib -levent 형태로 라이브러리 지정을 해야되더군요. ocamlc로 byte compile할때는 -cclib 를 지정하지 않아도 됩니다.

Ocaml로 작성한 세가지 echo server 소스입니다. ( libevent / fork / thread )



Trackback Address :: http://mix1009.net/trackback/74


◀ PREV : [1] : .. [33] : [34] : [35] : [36] : [37] : [38] : [39] : [40] : [41] : .. [99] : NEXT ▶



//]]>