F# 和 UdpClient 接收器
F# and UdpClient reciver
我正在使用 .Net UdpCLient 在 f# 中创建 UDP 接收器 class,它看起来很简单:
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)
}
为了让它保持活力,我正在使用另一个 属性,它在其中使用了 rec 函数,它看起来像:
let Watcher (ip: IPAddress, port : int32) : unit =
let rec listenerWatcher () =
async {
try
do! Start (ip, port)
return! listenerWatcher()
with | :? UdpClientDisposedException ->
return ()
}
listenerWatcher() |> Async.Start
调用类型很简单:
UdpReceiver.Watcher (ip, port) (* where UdpReceiver is module name *)
我的问题是我只收到第一个传入的包,就像监听器在收到第一个包后关闭,可能是什么问题?
也许您的问题是您发送包裹的速度太快了。收到第一个包后,需要时间重新启动接收方,但同时发送方仍在发送下一个包。
不确定您的确切意图,但我认为您应该只启动(设置)接收器一次,然后重复接收传入的包,并且只有在出现错误(抛出异常)时才重新启动接收器。
顺便说一下,您的代码在 F# 中并不是真正地道,您应该:
- 比元组更喜欢分离参数,它增加了使用柯里化的机会。
- 仅在需要时才使用类型注释,这样可以缩短代码。
- 命名函数,使其成为动词而不是名词,并使用驼峰命名法。
我会重写你的代码如下:
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...
我正在使用 .Net UdpCLient 在 f# 中创建 UDP 接收器 class,它看起来很简单:
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)
}
为了让它保持活力,我正在使用另一个 属性,它在其中使用了 rec 函数,它看起来像:
let Watcher (ip: IPAddress, port : int32) : unit =
let rec listenerWatcher () =
async {
try
do! Start (ip, port)
return! listenerWatcher()
with | :? UdpClientDisposedException ->
return ()
}
listenerWatcher() |> Async.Start
调用类型很简单:
UdpReceiver.Watcher (ip, port) (* where UdpReceiver is module name *)
我的问题是我只收到第一个传入的包,就像监听器在收到第一个包后关闭,可能是什么问题?
也许您的问题是您发送包裹的速度太快了。收到第一个包后,需要时间重新启动接收方,但同时发送方仍在发送下一个包。
不确定您的确切意图,但我认为您应该只启动(设置)接收器一次,然后重复接收传入的包,并且只有在出现错误(抛出异常)时才重新启动接收器。
顺便说一下,您的代码在 F# 中并不是真正地道,您应该:
- 比元组更喜欢分离参数,它增加了使用柯里化的机会。
- 仅在需要时才使用类型注释,这样可以缩短代码。
- 命名函数,使其成为动词而不是名词,并使用驼峰命名法。
我会重写你的代码如下:
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...