src/Pure/General/socket_io.ML
author wenzelm
Wed, 16 Oct 2013 11:48:42 +0200
changeset 54340 18c621069bf8
parent 54339 26c790a6ce43
child 54342 fbcaa9f08879
permissions -rw-r--r--
prefer TCP_NODELAY -- avoid extra buffering due to Nagle's algorithm;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
50800
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
     1
(*  Title:      Pure/General/socket_io.ML
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
     2
    Author:     Timothy Bourke, NICTA
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
     3
    Author:     Makarius
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
     4
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
     5
Stream IO over TCP sockets.  Following example 10.2 in "The Standard
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
     6
ML Basis Library" by Emden R. Gansner and John H. Reppy.
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
     7
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
     8
Note: BinIO requires Poly/ML 5.5.x to work reliably.
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
     9
*)
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    10
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    11
signature SOCKET_IO =
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    12
sig
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    13
  val make_streams: Socket.active INetSock.stream_sock -> BinIO.instream * BinIO.outstream
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    14
  val open_streams: string -> BinIO.instream * BinIO.outstream
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    15
end;
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    16
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    17
structure Socket_IO: SOCKET_IO =
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    18
struct
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    19
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    20
fun make_streams socket =
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    21
  let
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    22
    val (host, port) = INetSock.fromAddr (Socket.Ctl.getSockName socket);
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    23
    val name = NetHostDB.toString host ^ ":" ^ string_of_int port;
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    24
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    25
    val rd =
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    26
      BinPrimIO.RD {
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    27
        name = name,
54339
26c790a6ce43 basic IO buffer size like for fifo -- imitate implicit flushing behaviour more closely;
wenzelm
parents: 50800
diff changeset
    28
        chunkSize = 4096,
50800
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    29
        readVec = SOME (fn n => Socket.recvVec (socket, n)),
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    30
        readArr = SOME (fn buffer => Socket.recvArr (socket, buffer)),
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    31
        readVecNB = NONE,
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    32
        readArrNB = NONE,
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    33
        block = NONE,
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    34
        canInput = NONE,
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    35
        avail = fn () => NONE,
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    36
        getPos = NONE,
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    37
        setPos = NONE,
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    38
        endPos = NONE,
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    39
        verifyPos = NONE,
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    40
        close = fn () => Socket.close socket,
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    41
        ioDesc = NONE
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    42
      };
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    43
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    44
    val wr =
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    45
      BinPrimIO.WR {
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    46
        name = name,
54339
26c790a6ce43 basic IO buffer size like for fifo -- imitate implicit flushing behaviour more closely;
wenzelm
parents: 50800
diff changeset
    47
        chunkSize = 4096,
50800
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    48
        writeVec = SOME (fn buffer => Socket.sendVec (socket, buffer)),
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    49
        writeArr = SOME (fn buffer => Socket.sendArr (socket, buffer)),
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    50
        writeVecNB = NONE,
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    51
        writeArrNB = NONE,
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    52
        block = NONE,
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    53
        canOutput = NONE,
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    54
        getPos = NONE,
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    55
        setPos = NONE,
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    56
        endPos = NONE,
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    57
        verifyPos = NONE,
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    58
        close = fn () => Socket.close socket,
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    59
        ioDesc = NONE
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    60
      };
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    61
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    62
    val in_stream =
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    63
      BinIO.mkInstream
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    64
        (BinIO.StreamIO.mkInstream (rd, Word8Vector.fromList []));
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    65
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    66
    val out_stream =
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    67
      BinIO.mkOutstream
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    68
        (BinIO.StreamIO.mkOutstream (wr, IO.BLOCK_BUF));
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    69
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    70
  in (in_stream, out_stream) end;
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    71
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    72
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    73
fun open_streams socket_name =
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    74
  let
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    75
    fun err () = error ("Bad socket name: " ^ quote socket_name);
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    76
    val (host, port) =
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    77
      (case space_explode ":" socket_name of
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    78
        [h, p] =>
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    79
         (case NetHostDB.getByName h of SOME host => host | NONE => err (),
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    80
          case Int.fromString p of SOME port => port | NONE => err ())
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    81
      | _ => err ());
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    82
    val socket: Socket.active INetSock.stream_sock = INetSock.TCP.socket ();
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    83
    val _ = Socket.connect (socket, INetSock.toAddr (NetHostDB.addr host, port));
54340
18c621069bf8 prefer TCP_NODELAY -- avoid extra buffering due to Nagle's algorithm;
wenzelm
parents: 54339
diff changeset
    84
    val _ = INetSock.TCP.setNODELAY (socket, true);
50800
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    85
  in make_streams socket end;
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    86
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    87
end;
c0fb2839d1a9 recovered buffered sockets from 11f622794ad6 -- requires Poly/ML 5.5.x;
wenzelm
parents:
diff changeset
    88