All pastes #836177 Raw Edit

Miscellany

public text v1 · immutable
#836177 ·published 2007-12-29 07:47 UTC
rendered paste body
(* routines for reading and writing while only blocking the
 * current thread of execution *)
let thread_read_line fd =
    let s = " " and r = ref "" in
    while (Unix.read fd s 0 1 > 0) && s.[0] <> '\n' do
        r := !r ^ s
    done; !r

let thread_write_string fd str =
    ignore (Unix.write fd str 0 (String.length str))

let thread_write_endline fd str =
    thread_write_string fd (str ^ "\n")

(*** actual networking code ***)

let gen_connection_num =
    let c = ref 0 in
    (fun () -> incr c; !c)

exception Done

(* just for something to do with our clients, unimportant *)
let counter = ref 0

class connection (sd, sa) = object (self)
    val socket = sd
    val addr = sa
    val mutable number = 0
    initializer
        number <- gen_connection_num ();

    method start () =
        Thread.create (fun x ->
            self#run x;
            self#stop x) ()

    method stop () =
        Unix.close socket

    method run () =
        try while true do
            (* do things here, terminate the thread with 'raise Done'.  as a
             * demonstration, we count for our clients, keeping track of a
             * server-global counter state *)
            let line = thread_read_line socket in
            counter := !counter + 1;
            thread_write_endline socket (string_of_int !counter)
        done with
            | Done -> () (* thread terminated normally *)
            | exn -> print_string (Printexc.to_string exn); print_newline ()
end

class serv_socket p = object (self)
    val port = p
    val mutable sock = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0
    val queue_limit = 3

    initializer
        Unix.bind sock (Unix.ADDR_INET(Unix.inet_addr_any, port));
        Unix.listen sock queue_limit

    method private client_addr = function
        Unix.ADDR_INET(host, _) -> Unix.string_of_inet_addr host
        | _ -> "Client connecting from non-internet host???"

    method run () =
        while true do
            let (sd, sa) = Unix.accept sock in
            let connection = new connection (sd, sa) in
            ignore (connection#start ())
        done
end

let _ =
    let port = 4226 in
    Unix.handle_unix_error (fun () ->
        let s = new serv_socket port in s#run ()) ()