Ocaml 如何发送多个TCP消息并在其中一个消息成功后继续

Ocaml 如何发送多个TCP消息并在其中一个消息成功后继续,ocaml,ocaml-lwt,Ocaml,Ocaml Lwt,我目前正在编写一些网络代码,我需要发送大量消息,然后等待一个响应 假设我有一个函数返回套接字的输入和输出通道,我有: let resps = List.map uris ~f:(fun uri -> let%lwt (ic,oc) = connect uri in let%lwt () = Lwt_io.write_value oc msg in Lwt_io.read_value ic ) in Lwt.pick resps 我对这一点的理解是,pick应在履行了resp

我目前正在编写一些网络代码,我需要发送大量消息,然后等待一个响应

假设我有一个函数返回套接字的输入和输出通道,我有:

let resps = List.map uris ~f:(fun uri -> 
  let%lwt (ic,oc) = connect uri in
  let%lwt () = Lwt_io.write_value oc msg in
  Lwt_io.read_value ic
) in
Lwt.pick resps
我对这一点的理解是,pick应在履行了
resps
中的承诺后取消任何正在进行的请求。问题是,如果这些连接中的任何一个失败/被拒绝,就会引发异常
Unix.econnreference

我的问题是什么是强制
Lwt的正确语义。选择
忽略异常

到目前为止,我想到的选择是抓住机会 请求中的异常明确性:

let resps = List.map uris ~f:(fun uri -> 
  try
  let%lwt (ic,oc) = connect uri in
  let%lwt () = Lwt_io.write_value oc msg in
  Lwt_io.read_value ic
  with Unix_error (e,_,_) -> ...
) in
Lwt.pick resps
但是我不确定在什么情况下,
Lwt.pick
会看到这些承诺被拒绝

更新:我现在正在用可撤销、不可兑现的承诺处理错误:

fst @@ Lwt.task ()

这让人感觉很不舒服,但到目前为止似乎还有效。

显式处理异常是正确的。如果您明确拒绝Lwt承诺(使用
Lwt.fail
),或者Lwt在本应返回承诺的回调中捕获异常(如传递给
Lwt.bind
),Lwt承诺将被拒绝


但是,对于处理调用Lwt的代码中的异常,您必须使用
try%Lwt
而不是普通的
try

,因此,就向多个主机发送消息并仅等待一个响应的语义而言,我应该处理通信引起的任何异常(
econnreflused
等)那么这些处理程序的返回应该是什么呢?只需提出
Lwt.Cancelled
,或返回一个永远无法解决的承诺?如果您试图返回一个永远无法解决的承诺,您可能不应该首先将这些承诺传递给
Lwt.pick
。您是在等待一个特定的响应,还是等待第一个响应?如果是等待一个特定的响应(如您的评论所示),则仅绑定该响应。如果第一个响应(如初始问题所示),但您希望忽略异常,那么最干净的方法可能是使用
Lwt创建最终承诺。提前等待
,并让第一个成功的响应解决该承诺
Lwt.pick
不适合此用例,因为您需要的行为与它提供的稍有不同。我正在寻找第一个要解决的行为,我认为这是
Lwt.pick
的语义,除非我弄错了?您是正确的,这些是
Lwt.pick
的语义,
Lwt.pick
将报告第一个解决方案,无论是满足还是拒绝。似乎你在寻找第一次实现,如果第一次承诺被拒绝,你希望拒绝被忽视,并继续等待。这些语义与
Lwt.pick
的语义不完全相同,因此您可能需要自己的助手函数,或者只需一次性使用
Lwt.wait
:)