I am creating UDP receiver in f# using .Net UdpCLient class and it looks simple:
let Start (ip: IPAddress, port : int32) : Async<unit> =
async {
try
let endpoint = IPEndPoint(ip, port)
use receivingClient = new UdpClient();
receivingClient.Client.Bind(endpoint)
let! receiveResult = receivingClient.ReceiveAsync() |> Async.AwaitTask
let receiveBytes = receiveResult.Buffer
printfn "%A" receiveBytes
with | ex -> raise (ex)
}
And to keep it alive I am using another property that uses rec function in it and it looks like:
let Watcher (ip: IPAddress, port : int32) : unit =
let rec listenerWatcher () =
async {
try
do! Start (ip, port)
return! listenerWatcher()
with | :? UdpClientDisposedException ->
return ()
}
listenerWatcher() |> Async.Start
and call with type is simple:
UdpReceiver.Watcher (ip, port) (* where UdpReceiver is module name *)
My problem is that I am only receiving first incoming package, like listener is shutting down after receiving first one, what could be the problem?
Maybe your problem is that you are sending packages too fast. After receiving the first package, it takes time to start again the receiver, but in the meanwhile the sender is still sending the next packages.
Not sure what is your exact intention, but I think you should start (setup) the receiver only one time, then repeatedly receive the incoming packages, and only restart the receiver when something wrong happens (exceptions are thrown).
By the way, your code is not really idiomatic in F#, you should:
Prefer separated parameters over tuples, it increases the chance of using currying.
Use type annotation only when needed, it makes code shorter.
Name functions so that they are verbs not nouns, and use camelCase style.
I would rewrite your code as below:
let start (ip: IPAddress) port =
let endpoint = IPEndPoint (ip, port)
let receivingClient = new UdpClient ()
receivingClient.Client.Bind endpoint
let rec loop () = async {
printfn "Waiting..."
let! receiveResult = receivingClient.ReceiveAsync () |> Async.AwaitTask
let receiveBytes = receiveResult.Buffer
printfn "Receive: %A" receiveBytes
return! loop ()
}
loop ()
let watch ip port =
let rec loop () = async {
try
return! start ip port
with ex ->
printfn "Error: %s" ex.Message
return! loop ()
}
loop ()
// in main function or somewhere:
watch ... ... |> Async.Start...
Related
I want to write a simple load balancer for some requests coming into a C# web api app.
(I only use the C# stuff as a convenient way to create a web server).
Whats the best way to approach this? (I havent really done any mailbox stuff in F#)
If I were to use mailboxes/agents...then I post the request as a message, fine...but how do I get the response back to web api request handler?
Isnt it all fire and forget? (I have, ironically, done some erlang)
(I CAN have a simple mutable global index of which is the next worker service to handle the request...but this is my opportunity to do it nicely).
actually I think I may have done something very similar to this in erlang, and I think the initiator would pass a return address where to send the message back (and the return address was the process id of the initiator), it would then wait for the response, and when it gets it (or times out), it would then do whatever it needed to do.
Is that a sensible mechanism in F#?
------------------------ edit ------------------------
So, https://www.codemag.com/Article/1707051/Writing-Concurrent-Programs-Using-F
describes a similar set up and it seems I need to use, and actually this works,
but it ISNT quite the same mechanism as my Erlang suggestion about.
Here each client sends a PostAndReply, and then waits for the response before replying back.....that seems unnecessary, ideally the reply would go all the way back to the origin, and the intermediaries would fire and forget in between.
open System
type Message = string * AsyncReplyChannel<string>
[<EntryPoint>]
let main argv =
let myFirstAgent =
MailboxProcessor<Message>.Start(fun inbox ->
let rec loop () =
async {
let! (message, replyChannel) = inbox.Receive()
replyChannel.Reply (String.Format ("1. Received message: {0}", message))
do! loop ()
}
loop ())
let mySecondAgent =
MailboxProcessor<Message>.Start(fun inbox ->
let rec loop () =
async {
let! (message, replyChannel) = inbox.Receive()
replyChannel.Reply (String.Format ("2. Received message: {0}", message))
do! loop ()
}
loop ())
let agents = [ myFirstAgent; mySecondAgent ]
let replyAgent =
MailboxProcessor<Message>.Start(fun inbox ->
let rec loop index =
async {
let! (message, replyChannel) = inbox.Receive()
let reply = (agents.Item index).PostAndReply(fun rc -> message,rc)
replyChannel.Reply reply
do! loop ((index + 1) % 2)
}
loop 0)
let foo = replyAgent.PostAndReply(fun rc -> "Hello", rc)
let foo1 = replyAgent.PostAndReply(fun rc -> "Hello", rc)
let foo2 = replyAgent.PostAndReply(fun rc -> "Hello", rc)
let foo3 = replyAgent.PostAndReply(fun rc -> "Hello", rc)
let foo4 = replyAgent.PostAndReply(fun rc -> "Hello", rc)
//myFirstAgent.Post "Hello!"
printfn "Hello World from F#!"
System.Console.ReadLine() |> ignore
0 // return an integer exit code
D'oh, what I need to do is actually UNDERSTAND the example, rather than just hack together code!
if the reply agent just forwards it...then we're done.
let replyAgent =
MailboxProcessor<Message>.Start(fun inbox ->
let rec loop index =
async {
let! (message, replyChannel) = inbox.Receive()
let reply = (agents.Item index).Post(message, replyChannel)
do! loop ((index + 1) % 2)
}
loop 0)
I am new to f# and I have a question about timeout in asynchornization operations, this is simple communication using serial com ports, so I have a method/function:
let SendMessenge(port : Ports.SerialPort, messange: string) =
async {
do! port.AsyncWriteLine messange
let! response = port.AsyncReadLine() // this returns a string
return response
}
|> Async.RunSynchronously // the place i fiddled with
All communication (messengering) is controlled in this module:
type SerialPort with
member this.AsyncWriteLine(messange : string) = this.BaseStream.AsyncWrite(this.Encoding.GetBytes(messange + "\n"))
member this.AsyncReadLine() =
async {
let messange_builder = StringBuilder()
let buffer_ref = ref (Array.zeroCreate<byte> this.ReadBufferSize)
let buffer = !buffer_ref
let last_char = ref 0uy
while !last_char <> byte '\n' do
let! readCount = this.BaseStream.AsyncRead buffer
last_char := buffer.[readCount-1]
messange_builder.Append (this.Encoding.GetString(buffer.[0 .. readCount-1])) |> ignore
messange_builder.Length <- messange_builder.Length-1
let response : string = messange_builder.ToString()
printfn "Response: %s" response
return response
}
Basically this works fine, it sends a message and receives response, But now I want to add a timeout, in case i am connect. I tried to fiddle with
|> Async.RunSynchronously(???, timeout, cancel_token)
but with no luck. As i see in documentation it takes timeout and cancellation token and Async, What would be this T0 generic parameter in my case?
What happens is that Async.RunSynchronously is a static method, rather than a method function, so it takes its arguments with tuple syntax. So you can't partially apply it and pipe the last argument into it.
You can do this:
let response = async {
// ...
}
Async.RunSynchronously(response, timeout, cancel_token)
or if you really want to pipe:
async {
// ...
}
|> fun response -> Async.RunSynchronously(response, timeout, cancel_token)
I created the following test code - .Net core 2.1 console application. It prints the following message only
TestActor received message MyTask ("Test1","Test1") from [akka://MySystem/user/Scheduler#1426101451]
But the message Ok 0 cannot be received by the actor scheduler?
open System
open Akka.FSharp
open Akka
type MyTask = MyTask of item1: string * item2: string
let system = System.create "MySystem" <| Configuration.load ()
let scheduler (actors: Actor.IActorRef) (mailbox: Actor<Result<int, string>>) =
let rec loop (list: int list list) = actor {
let! m = mailbox.Receive ()
let sender = mailbox.Sender ()
let akkaName = mailbox.Self.Path.Name
printfn "%s received message %A from %A" akkaName m sender
return! loop []
}
actors <! MyTask("Test1", "Test1")
loop []
let processor (mailbox: Actor<MyTask>) =
let rec loop () = actor {
let! m = mailbox.Receive ()
let sender = mailbox.Sender ()
let akkaName = mailbox.Self.Path.Name
printfn "%s received message %A from %A" akkaName m sender
sender <! Ok 0 // scheduler cannot receive this message?
return! loop ()
}
loop ()
[<EntryPoint>]
let main argv =
let actor = spawn system "TestActor" processor
spawn system "Scheduler" (scheduler actor) |> ignore
system.WhenTerminated.Wait()
0
Update:
It works after I changed the parameter from (mailbox: Actor<Result<int, string>>) to (mailbox: Actor<_>)?
The scheduler isn't the sender of the MyTask message to which the processor is replying, because you are doing the tell (<!) from outside the actor computation. That means it's basically being sent with no sender. You can use the Tell method on IActorRef to send with an explicit sender, since you want to send it from outside the context of your actor computation:
actors.Tell(MyTask("Test1", "Test1"), mailbox.Self)
EDIT
Another issue is that the mailbox parameter to the scheduler is typed as Actor<Result<int, string>>, but since Ok 0 will be inferred as Result<int,obj> in your context, it won't match the actor type signature, and the message will be ignored. When defining an actor with a specific message type, any messages of a different type will be ignored.
I have write a f# named pipe server:
let a=new NamedPipeServerStream("a")
a.WaitForConnection()
let reader=new StreamReader(a)
let rec loop()=
let b=reader.ReadLine()
match b with
|b' when String.IsNullOrEmpty(b')->()
|_->
Console.WriteLine b
loop()
loop()
This server can work,but for only one client.When client is quit,the server quit too.
How can I write a named pipe server,like tcp server,that can server many clients,and never stop?
As per the C# example here MSDN you need to read from the NamedPipeServerStream using multiple threads to service multiple clients (consider using Async methods in the loop function). The following example can service up to 4 clients at the same time.
let MaxPipes = 4
let pipe = new NamedPipeServerStream("a", PipeDirection.InOut,MaxPipes)
let rec loop () = async{
pipe.WaitForConnection()
let reader = new StreamReader(pipe)
let b = reader.ReadLine()
return! loop ()
}
for i in [1..MaxPipes] do
Async.Start (loop ())
Suppose I have a stream which only allows one request/response at a time but is used in several threads.
Requests/commands should be throttled such that a new request can only occur once
the previous request has been sent and a reply has been received.
The user would be able to do this
let! res = getResponse("longResp")
let! res2 = getResponse("shortResp")
and not really know or care about the throttle.
I have tried with a modified version of Tomas Petricek's Throttling Agent that allows async with return values, but this requires the user to call getResponse("..") |> Enqueue |> w.Post which is a recipe for disaster (in case they forget to do so).
Is there a good/idiomatic way of doing this in F#?
Then make it explicit in your type system that the returned type needs to be unwrapped with another function. So instead of returning an Async<'T> which as you pointed out can be called directly with Async.Start, rather return something like:
type Queuable<'T> = Queuable of Async<'T>
Then getResponse changes to return a Queueable:
let getResponse (s:string) =
let r =
async{
do! write to your stream
return! read from your stream
}
Queuable r
Provide a function that unwraps the Queuable:
let enqueue (Queuable q) = async{
return! processor.PostAndAsyncReply(fun replyChannel -> replyChannel,q)
}
The processor is an agent that simply runs the Async workflow. Something like this:
let processor = new MailboxProcessor<_>(fun inbox ->
let rec Loop() = async {
let! (r:AsyncReplyChannel<_>,job) = inbox.Receive()
let! res = job
r.Reply res
return! Loop()}
Loop())