[英]How to determine stream end in a asynchronous socket server
我正在嘗試用c#編寫異步套接字。 我閱讀了許多msdn文章,並找到了兩個示例: server , client 。
我理解了示例代碼,並以此來實現自己的異步套接字。 在該示例中,服務器檢查<EOF>
以確定流的結尾並發送響應。 我想知道在流結束時不檢查特殊文字。 我的想法是檢查(bytesRead > 0)
並遞歸調用handler.BeginReceive()
。 請參閱以下內容:
原版的
if (bytesRead > 0) {
// There might be more data, so store the data received so far.
state.sb.Append(Encoding.ASCII.GetString(
state.buffer,0,bytesRead));
// Check for end-of-file tag. If it is not there, read
// more data.
content = state.sb.ToString();
if (content.IndexOf("<EOF>") > -1) {
// All the data has been read from the
// client. Display it on the console.
Console.WriteLine("Read {0} bytes from socket. \n Data : {1}",
content.Length, content );
// Echo the data back to the client.
Send(handler, content);
} else {
// Not all data received. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
我的點子
if (received > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, received));
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state);
}
else
Send(handler, state.sb.ToString());
如果我用我的零件替換原始零件,程序將停止運行。 我猜想客戶端在SendCallback()
執行EndSend()
,並在StartClient()
receiveDone.WaitOne()
之后阻止線程。 我該如何通過? 是否有必要使用確定流結束的令牌?
還有其他好的示例代碼嗎? 我剛發現那兩個。
(證據。服務器應接收在線客戶端,並將其從該緩沖區放入循環緩沖區中,他應使用多線程讀取和處理記錄。)
編輯
如果我使用跟蹤:
if (receive > 0)
state.sb.Append(Encoding.UTF8.GetString(state.buffer, 0, receive));
if (receive == StateObject.BufferSize)
state.listener.BeginReceive(state.buffer, 0, StateObject.BufferSize, SocketFlags.None, new AsyncCallback(ReceiveCallback), state);
else
Send(state.listener, state.sb.ToString());
我想一切都很好。 可以嗎 還是想念我什么?
如果我將兩個if結合起來,它將無法再使用。 為什么?
if(receive > 0 || receive == StateObject.BufferSize)
-> if(receive > 0) // Not working.
您的代碼版本的問題是,總是在一種情況下(即當收到0
字節時)啟動BeginReceive
。 實際上,當您收到的數據量非零且小於緩沖區大小(有時恰好是緩沖區的大小)時,傳輸結束通常會發生。 接收0
字節將永遠不會發生,因為這意味着沒有傳輸 結束傳輸結束 。 假設發送方通過關閉連接來結束傳輸。
有多種指示傳輸結束的方法:
第一種方法的問題是關閉(和重新打開)連接通常很昂貴。 標頭的問題是,如果您錯過標頭(由於某些網絡問題),則會丟失–您不知道下一個標頭何時到達,因為您不知道當前數據包何時結束(標頭丟失)。 如果出現問題,最輕松的恢復將以某種形式提供EOF。 它不一定是<EOF>
字符串,它可以是(很可能)在常規數據流中永遠不會發生的任何事情。
話雖如此,沒有什么阻止您使用帶有EOF
的標頭組合或包含一個特殊序列標記記錄開頭的標頭的組合。
可以確定網絡流已結束的情況是遠程端正常關閉連接時。 這將使EndRead
返回零。 如果要將數據發送回遠程端,這當然不是最佳方法。 從本質上講,您將必須創建回客戶端的新連接,而不是重新使用初始連接。 當然,您可以執行此操作,但是通常無法很好地進行此操作,例如,如果客戶端位於NAT路由器后面。
該示例代碼在檢查EOF
執行的是強制應用程序級協議。 基礎網絡堆棧不了解它傳遞給應用程序的有效負載,因此無法確定概念性流已結束。 這是您的應用程序負責的事情。 檢查標簽或令牌是一種非常簡單的方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.