5 people like it.

tcpStream abstraction

Basic (but experimental) TCP stream wrappers to help make TCP more abstracted and cleaner. Giving the user just the impression of a 'stream' that one connects to and sends and receives. This helps promote composition. The first abstraction is 'stream', really just wrapping .NET stream functions so that read returns the read n bytes and write returns the stream, all functions take NetworkStream as the first parameters, followed by other parameters. Currently we don't care about timeouts, exceptions, or other nasty's.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
open System.Net
open System.Text 
open System.Net.Sockets

module stream =
  type stream               = NetworkStream
  let curry g b n           = g(b,0,n) |> ignore; b
  let read  (s : stream) n  = curry s.Read (Array.zeroCreate n) n
  let write (s : stream) b  = curry s.Write b b.Length; s
  let close (s : stream) b  = s.Close(); b
  let connect host port     = TcpClient(host,port).GetStream()

(* example *) 
let sendString host (data : string) =
  stream.connect host 80 
  |> fun stm -> 
     data
     |> Encoding.Default.GetBytes 
     |> stream.write stm 
     |> stream.read <| 256
     |> Encoding.Default.GetString
     |> stream.close stm

let data = "GET / HTTP/1.1\r\nHost: microsoft.com\r\n\r\n"

// not robust for all server types, just for demo, no exceptions.
let getServerHeader (s : string) =
  let needle = s.IndexOf "Server: "
  s.[needle..needle+24]

sendString "microsoft.com" data |> getServerHeader

(* val it : string = "Server: Microsoft-IIS/7.5" *)
namespace System
namespace System.Net
namespace System.Text
namespace System.Net.Sockets
type stream = NetworkStream

Full name: Script.stream.stream
Multiple items
type NetworkStream =
  inherit Stream
  new : socket:Socket -> NetworkStream + 3 overloads
  member BeginRead : buffer:byte[] * offset:int * size:int * callback:AsyncCallback * state:obj -> IAsyncResult
  member BeginWrite : buffer:byte[] * offset:int * size:int * callback:AsyncCallback * state:obj -> IAsyncResult
  member CanRead : bool
  member CanSeek : bool
  member CanTimeout : bool
  member CanWrite : bool
  member Close : timeout:int -> unit
  member DataAvailable : bool
  member EndRead : asyncResult:IAsyncResult -> int
  ...

Full name: System.Net.Sockets.NetworkStream

--------------------
NetworkStream(socket: Socket) : unit
NetworkStream(socket: Socket, ownsSocket: bool) : unit
NetworkStream(socket: Socket, access: System.IO.FileAccess) : unit
NetworkStream(socket: Socket, access: System.IO.FileAccess, ownsSocket: bool) : unit
val curry : g:('a * int * 'b -> 'c) -> b:'a -> n:'b -> 'a

Full name: Script.stream.curry
val g : ('a * int * 'b -> 'c)
val b : 'a
val n : 'b
val ignore : value:'T -> unit

Full name: Microsoft.FSharp.Core.Operators.ignore
val read : s:stream -> n:int -> byte []

Full name: Script.stream.read
val s : stream
val n : int
NetworkStream.Read(buffer: byte [], offset: int, size: int) : int
module Array

from Microsoft.FSharp.Collections
val zeroCreate : count:int -> 'T []

Full name: Microsoft.FSharp.Collections.Array.zeroCreate
val write : s:stream -> b:byte [] -> stream

Full name: Script.stream.write
val b : byte []
NetworkStream.Write(buffer: byte [], offset: int, size: int) : unit
property System.Array.Length: int
val close : s:stream -> b:'a -> 'a

Full name: Script.stream.close
System.IO.Stream.Close() : unit
NetworkStream.Close(timeout: int) : unit
val connect : host:string -> port:int -> NetworkStream

Full name: Script.stream.connect
val host : string
val port : int
Multiple items
type TcpClient =
  new : unit -> TcpClient + 3 overloads
  member Available : int
  member BeginConnect : host:string * port:int * requestCallback:AsyncCallback * state:obj -> IAsyncResult + 2 overloads
  member Client : Socket with get, set
  member Close : unit -> unit
  member Connect : remoteEP:IPEndPoint -> unit + 3 overloads
  member Connected : bool
  member EndConnect : asyncResult:IAsyncResult -> unit
  member ExclusiveAddressUse : bool with get, set
  member GetStream : unit -> NetworkStream
  ...

Full name: System.Net.Sockets.TcpClient

--------------------
TcpClient() : unit
TcpClient(localEP: IPEndPoint) : unit
TcpClient(family: AddressFamily) : unit
TcpClient(hostname: string, port: int) : unit
val sendString : host:string -> data:string -> string

Full name: Script.sendString
val data : string
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = System.String

Full name: Microsoft.FSharp.Core.string
module stream

from Script
val stm : NetworkStream
type Encoding =
  member BodyName : string
  member Clone : unit -> obj
  member CodePage : int
  member DecoderFallback : DecoderFallback with get, set
  member EncoderFallback : EncoderFallback with get, set
  member EncodingName : string
  member Equals : value:obj -> bool
  member GetByteCount : chars:char[] -> int + 3 overloads
  member GetBytes : chars:char[] -> byte[] + 5 overloads
  member GetCharCount : bytes:byte[] -> int + 2 overloads
  ...

Full name: System.Text.Encoding
property Encoding.Default: Encoding
Encoding.GetBytes(s: string) : byte []
Encoding.GetBytes(chars: char []) : byte []
Encoding.GetBytes(chars: char [], index: int, count: int) : byte []
Encoding.GetBytes(chars: nativeptr<char>, charCount: int, bytes: nativeptr<byte>, byteCount: int) : int
Encoding.GetBytes(s: string, charIndex: int, charCount: int, bytes: byte [], byteIndex: int) : int
Encoding.GetBytes(chars: char [], charIndex: int, charCount: int, bytes: byte [], byteIndex: int) : int
val write : s:stream.stream -> b:byte [] -> stream.stream

Full name: Script.stream.write
val read : s:stream.stream -> n:int -> byte []

Full name: Script.stream.read
Encoding.GetString(bytes: byte []) : string
Encoding.GetString(bytes: byte [], index: int, count: int) : string
val close : s:stream.stream -> b:'a -> 'a

Full name: Script.stream.close
val data : string

Full name: Script.data
val getServerHeader : s:string -> string

Full name: Script.getServerHeader
val s : string
val needle : int
System.String.IndexOf(value: string) : int
System.String.IndexOf(value: char) : int
System.String.IndexOf(value: string, comparisonType: System.StringComparison) : int
System.String.IndexOf(value: string, startIndex: int) : int
System.String.IndexOf(value: char, startIndex: int) : int
System.String.IndexOf(value: string, startIndex: int, comparisonType: System.StringComparison) : int
System.String.IndexOf(value: string, startIndex: int, count: int) : int
System.String.IndexOf(value: char, startIndex: int, count: int) : int
System.String.IndexOf(value: string, startIndex: int, count: int, comparisonType: System.StringComparison) : int
Next Version Raw view Test code New version

More information

Link:http://fssnip.net/hg
Posted:9 years ago
Author:David Klein
Tags: streams , networking , tcp