對不起,這個帖子很長。我想使用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