tags:

views:

147

answers:

2

Hi

I am new to F#. I am trying to communicate with java from F# using named pipe. The code below works but I am not sure if there is a better way to do this (I know the infinite loop is a bad idea but this is just a proof of concept) if anyone have any idea to improve this code please post your comments.

Thanks in advance Sudaly

open System.IO
open System.IO.Pipes
exception OuterError of string


let continueLooping = true
while continueLooping do
    let pipeServer = new NamedPipeServerStream("testpipe", PipeDirection.InOut, 4)
    printfn "[F#] NamedPipeServerStream thread created."

    //wait for connection
    printfn "[F#] Wait for a client to connect"
    pipeServer.WaitForConnection()

    printfn "[F#] Client connected."
    try
        // Stream for the request. 
        let sr = new StreamReader(pipeServer)
        // Stream for the response. 
        let sw = new StreamWriter(pipeServer)
        sw.AutoFlush <- true;

        // Read request from the stream. 
        let echo = sr.ReadLine();

        printfn "[F#] Request message: %s" echo

        // Write response to the stream.
        sw.WriteLine("[F#]: " + echo)

        pipeServer.Disconnect()

    with
    | OuterError(str) -> printfn "[F#]ERROR: %s" str

    printfn "[F#] Client Closing."
    pipeServer.Close()
+2  A: 

Well, it doesn't look like anything is throwing OuterError, so I would remove that exception type and unused handling.

I am unsure about your experience level or what type of "better" you are looking for. You way want to read F# async on the server to learn more about async and avoiding blocking threads.

Brian
+2  A: 

Below you can find a few modifications to your code. Your question is pretty vague so I can't tell exactly where you're wishing to improve your code, but my suggestion uses recursion instead of the while loop (don't worry about stack overflows, F# can handle recursion very well and the whole recursive bit will be optimized into a loop at compile time), makes use of the use keyword (like C#'s using) and will swallow any exception happening in the process of the communication with the client. If an exception occurs, the server will not listen for other connections.

open System.IO
open System.IO.Pipes

let main() =
    printfn "[F#] NamedPipeServerStream thread created."
    let pipeServer = new NamedPipeServerStream("testpipe", PipeDirection.InOut, 4)
    let rec loop() =
        //wait for connection
        printfn "[F#] Wait for a client to connect"
        pipeServer.WaitForConnection()

        printfn "[F#] Client connected."
        try
            // Stream for the request. 
            use sr = new StreamReader(pipeServer)
            // Stream for the response. 
            use sw = new StreamWriter(pipeServer, AutoFlush = true)

            // Read request from the stream. 
            let echo = sr.ReadLine();

            printfn "[F#] Request message: %s" echo

            // Write response to the stream.
            echo |> sprintf "[F#]: %s" |> sw.WriteLine

            pipeServer.Disconnect()
            if [A CONDITION WHICH TELLS YOU THAT YOU WANT ANOTHER CONNECTION FROM THE CLIENT] then loop()
        with
        | _ as e -> printfn "[F#]ERROR: %s" e.Message
    loop()
    printfn "[F#] Client Closing."
    pipeServer.Close()

Also please notice how the AutoFlush is set within the call to the constructor and how the pipeline operator is used to write the echo to the pipe, resulting in what looks (in my opinion) like cleaner code.

emaster70