如何使用F#异步接收和发送UDP?

时间:2018-08-12 21:15:57

标签: asynchronous f# udp

我正在尝试通过UDP创建消息传递应用程序,并使其能够同时连续发送和接收。我不知道该如何实现,并且尝试了一些方法。以下是我到目前为止的代码,有人可以指出我做错了什么或需要添加什么?谢谢。

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

1 个答案:

答案 0 :(得分:2)

代码中一个明显的问题是,您创建了一个异步计算receive,然后忽略了它,而没有启动它。这意味着您当前的版本仅在发送。

我假设您打算在后台启动接收过程。为此,我们首先将receivesend定义为两个单独的异步函数:

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 }

现在,有多种不同的“同时”发送和接收方式,具体取决于您“同时”的含义。您可以在后台开始接收,然后同时发送,然后等待直到发送和接收都完成后再循环:

let rec loop() = async {
    let! wait = Async.StartChild (receive ())
    do! send () 
    do! wait
    return! loop() }

loop() |> Async.Start

或者,您也可以启动两个循环,一个循环保持发送,另一个循环保持尽可能快的接收速度:

let rec loop1() = async {
    do! receive ()
    return! loop1() }

let rec loop2() = async {
    do! send ()
    return! loop2() }

loop1() |> Async.Start
loop2() |> Async.Start