从Observables创建TcpListener是个好主意吗?

时间:2017-10-04 22:29:33

标签: f# observable tcplistener

在尝试学习一些反应式编程的应用程序时,我一直在玩FSharp.Control.Reactive库。使用.NET TcpListener类侦听客户端是一个被动的过程,因此我决定使用Observables在F#中创建一个服务器(松散的术语)。我的测试用例是来自天文程序(Stellarium)的单个客户端连接,它在20字节的tcp套接字流中发送星形的天体坐标。我在下面的代码片段工作,但是使用Observables订阅TcpListener和连接的任何最终客户端流是一个好主意,或者实际上是否实用?什么是优势或劣势?

open System
open System.Net
open System.Net.Sockets
open System.Threading
open System.Reactive
open System.Reactive.Linq
open System.Reactive.Concurrency
open System.Reactive.Disposables
open FSharp.Control.Reactive.Builders
open FSharp.Control.Reactive.Observable
open FSharp.Control.Reactive.Disposables

type TcpListener with
    member l.AcceptClientAsync = async {
        let! client = Async.AwaitTask <| l.AcceptSocketAsync()
        return client
    }

let readCoordinates(coords : byte[]) =
    let raInt = BitConverter.ToUInt32(coords, 12)
    let decInt = BitConverter.ToInt32(coords, 16)

    let ra_h = float raInt * 12.0 / 2147483648.0
    let dec_h = float decInt * 90.0 / 1073741824.0

    if (coords.Length > 0) then
        Some (ra_h, dec_h)
    else
        None

let listen() = 
    let ipAddr = IPAddress.Any
    let endpoint = IPEndPoint(ipAddr, 10001)
    let listener = TcpListener(endpoint)

    listener.Start()

    observe.While ((fun () -> true), ofAsync(listener.AcceptClientAsync))
    |> bind( (fun socket -> observe.Yield(new NetworkStream(socket))) )
    |> bind(fun stream -> observe.While( (fun _ -> true), ofAsync(stream.AsyncRead(20)) ))
    |> map (fun bytes -> readCoordinates bytes)


[<EntryPoint>]
let main argv = 

    listen()
    |> subscribe (fun coords -> printfn "Target Coordinates %A" coords)
    |> ignore


    printfn "Hit enter to continue"
    Console.Read() |> ignore

    0 

0 个答案:

没有答案