I am trying to make a messaging application over UDP, and get it to be able to continuously send and receive at the same time. I don't know how to achieve this and have tried a few things. Below is the code I have so far, could somebody point out what I'm doing wrong or what I need to add? Thank you.
open System
open System.Net
open System.Net.Sockets
open System.Text
printfn "Receive port: "
let receivePort = Console.ReadLine() |> int
let receivingClient = new UdpClient(receivePort)
let ReceivingIpEndPoint = new IPEndPoint(IPAddress.Any, 0)
printfn "Send address: "
let sendAddress = IPAddress.Parse(Console.ReadLine())
printfn "Send port: "
let sendPort = Console.ReadLine() |> int
let sendingClient = new UdpClient()
let sendingIpEndPoint = new IPEndPoint(sendAddress, sendPort)
let rec loop() =
let receive = async {
try
let! receiveResult = receivingClient.ReceiveAsync() |> Async.AwaitTask
let receiveBytes = receiveResult.Buffer
let returnData = Encoding.ASCII.GetString(receiveBytes)
printfn "%s" returnData
with
| error -> printfn "%s" error.Message
}
receive |> ignore
printfn "Send message: "
let (sendBytes: byte array) = Encoding.ASCII.GetBytes(Console.ReadLine())
try
sendingClient.Send(sendBytes, sendBytes.Length, sendingIpEndPoint) |> ignore
with
| error -> printfn "%s" error.Message
loop()
loop()
Console.Read() |> ignore
One obvious issue with your code is that you create an asynchronous computation receive and then ignore it, without ever starting it. This means that your current version is only sending.
I assume that you intended to start the receiving process in the background. To do that, let's first define receive and send as two separate asynchronous functions:
let receive () = async {
try
let! receiveResult = receivingClient.ReceiveAsync() |> Async.AwaitTask
let receiveBytes = receiveResult.Buffer
let returnData = Encoding.ASCII.GetString(receiveBytes)
printfn "%s" returnData
with
| error -> printfn "%s" error.Message }
let send () = async {
printfn "Send message: "
let (sendBytes: byte array) = Encoding.ASCII.GetBytes(Console.ReadLine())
try
sendingClient.Send(sendBytes, sendBytes.Length, sendingIpEndPoint) |> ignore
with
| error -> printfn "%s" error.Message }
Now, there are different ways to send and receive "at the same time" depending on what exactly you mean by "at the same time". You can start receiving in the background, then send at the same time and then wait until both sending and receiving completes before looping:
let rec loop() = async {
let! wait = Async.StartChild (receive ())
do! send ()
do! wait
return! loop() }
loop() |> Async.Start
Alternatively, you could also start two loops, one that keeps sending and another one that keeps receiving as fast as they can:
let rec loop1() = async {
do! receive ()
return! loop1() }
let rec loop2() = async {
do! send ()
return! loop2() }
loop1() |> Async.Start
loop2() |> Async.Start
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With