对不起,这个帖子很长。我想使用TcpListener
来侦听端口,处理不同(后台)线程中传入连接请求的繁重提升,然后在准备就绪时将响应发送回客户端。我已经阅读了MSDN上的很多代码和示例,并为服务器提供了以下实现。使TcpListener异步处理连接的正确方法是什么?
对于所有下面的实施方式的,请假设以下变量:
let sva = "127.0.0.1"
let dspt = 32000
let respondToQuery (ns_ : NetworkStream) (bta_ : byte array) : unit =
// DO HEAVY LIFTING
()
实施1(普通纸,同步服务器;我的the code from this MSDN page翻译)
let runSync() : unit =
printfn "Entering runSync()"
let (laddr : IPAddress) = IPAddress.Parse sva
let (svr : TcpListener) = new TcpListener (laddr, dspt)
try
svr.Start()
let (bta : byte array) = Array.zeroCreate<byte> imbs
while true do
printfn "Listening on port %d at %s" dspt sva
let (cl : TcpClient) = svr.AcceptTcpClient()
let (ns : NetworkStream) = cl.GetStream()
respondToQuery ns bta
cl.Close()
svr.Stop()
printfn "Exiting runSync() normally"
with
| excp ->
printfn "Error: %s" excp.Message
printfn "Exiting runSync() with error"
实现2 (我的翻译代码on this MSDN page)
let runAsyncBE() : unit =
printfn "Entering runAsyncBE()"
let (tcc : ManualResetEvent) = new ManualResetEvent (false)
let (bta : byte array) = Array.zeroCreate<byte> imbs
let datcc (ar2_ : IAsyncResult) : unit =
let tcpl2 = ar2_.AsyncState :?> TcpListener
let tcpc2 = tcpl2.EndAcceptTcpClient ar2_
let (ns2 : NetworkStream) = tcpc2.GetStream()
respondToQuery ns2 bta
tcpc2.Close()
tcc.Set() |> ignore
let rec dbatc (tcpl2_ : TcpListener) : unit =
tcc.Reset() |> ignore
printfn "Listening on port %d at %s" dspt sva
tcpl2_.BeginAcceptTcpClient (new AsyncCallback (datcc), tcpl2_) |> ignore
tcc.WaitOne() |> ignore
dbatc tcpl2_
let (laddr : IPAddress) = IPAddress.Parse sva
let (tcpl : TcpListener) = new TcpListener (laddr, dspt)
try
tcpl.Start()
dbatc tcpl
printfn "Exiting try block"
printfn "Exiting runAsyncBE() normally"
with
| excp ->
printfn "Error: %s" excp.Message
printfn "Exiting runAsyncBE() with error"
实现3(我基于the MSDN page for asynchronous workflows实现)现在
let runAsyncA() : unit =
printfn "Entering runAsyncA()"
let (laddr : IPAddress) = IPAddress.Parse sva
let (svr : TcpListener) = new TcpListener (laddr, dspt)
try
svr.Start()
let (bta : byte array) = Array.zeroCreate<byte> imbs
while true do
printfn "Listening on port %d at %s" dspt sva
let (cl : TcpClient) = svr.AcceptTcpClient()
let (ns : NetworkStream) = cl.GetStream()
async {respondToQuery ns bta} |> Async.RunSynchronously
cl.Close()
svr.Stop()
printfn "Exiting runAsyncA() normally"
with
| excp ->
printfn "Error: %s" excp.Message
printfn "Exiting runAsyncA() with error"
,从我的MSDN文档的阅读,我本来以为Implementation 3
将是最快的。但是当我用多台机器的多个查询来访问服务器时,它们的运行速度大致相同。这使我相信我一定在做错事。
或者是Implementation 2
或Implementation 3
“正确”的方式来实现一个TcpListener
,做了繁重的背景下,当它完成,同时允许其他客户或许还连接并开始另一个返回到客户端的响应任务在另一个后台线程?如果没有,请告诉我应该阅读哪些类(或教程)?
非常感谢! – Shredderroy 2013-03-07 14:59:40
你可以使用'use client = client'而不是'try..finally'吗? – 2013-03-10 12:10:16