在C#中我使用的是TcpListener / TcpClient的异步版本,我通过回调方法链接这些版本,以便在回调完成时发布另一个Accept / Read。这是一个例子(未经测试):
public void Start()
{
TcpListener listener = new TcpListener(IPAddress.Any, 3000);
listener.Start();
PostAccept(listener);
}
private void PostAccept(TcpListener listener)
{
listener.BeginAcceptTcpClient(AcceptCallback, listener);
}
private void AcceptCallback(IAsyncResult ar)
{
var listener = ar.AsyncState as TcpListener;
if (listener == null)
{
return;
}
// get the TcpClient and begin a read chain in a similar manner
PostAccept(listener);
}
我的问题是我如何在F#中建模类似的东西?我会使用async关键字吗? BeginAcceptTcpClient,BeginRead等之后的代码本质上是将在回调函数中执行的代码吗?例如,这是正确的吗?
let accept(listener:TcpListener) = async {
let! client = listener.AsyncAcceptTcpClient()
// do something with the TcpClient such as beginning a Read chain
accept(listener)
return()
}
上面的代码不起作用,因为未定义accept,并且在技术上标记它是不正确的,因为它不是一个递归方法?
答案 0 :(得分:5)
@ kvb的回答是正确的,也是惯用的。
只是想指出你可以使用(喘气)循环:
let accept(t:TcpListener) =
let completed = ref false
async {
while not(!completed) do
let! client = t.AsyncAcceptTcpClient()
if client <> null then
Blah(client)
else
completed := true
}
(这是在我的浏览器中输入代码,希望它可以编译)。这很好,因为你当然不能在C#代码中使用循环(必须使用开始/结束回调来跨越多个方法)。
答案 1 :(得分:4)
我不确定你的意思是“这不是一种反悔的方法”;如果你从它自己的定义中引用一个函数,那么它就是一个递归函数。我对Sockets类没有多少经验,但也许你正在寻找的是这些内容?
let rec accept(t : TcpListener) =
async {
let! client = t.AsyncAcceptTcpClient()
// do some stuff with client here
do! accept(t)
}