簡體   English   中英

如何確定異步套接字服務器中的流結束

[英]How to determine stream end in a asynchronous socket server

我正在嘗試用c#編寫異步套接字。 我閱讀了許多msdn文章,並找到了兩個示例: serverclient

我理解了示例代碼,並以此來實現自己的異步套接字。 在該示例中,服務器檢查<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>字符串,它可以是(很可能)在常規數據流中永遠不會發生的任何事情。

話雖如此,沒有什么阻止您使用帶有EOF的標頭組合或包含一個特殊序列標記記錄開頭的標頭的組合。

可以確定網絡流已結束的情況是遠程端正常關閉連接時。 這將使EndRead返回零。 如果要將數據發送回遠程端,這當然不是最佳方法。 從本質上講,您將必須創建回客戶端的新連接,而不是重新使用初始連接。 當然,您可以執行此操作,但是通常無法很好地進行此操作,例如,如果客戶端位於NAT路由器后面。

該示例代碼在檢查EOF執行的是強制應用程序級協議。 基礎網絡堆棧不了解它傳遞給應用程序的有效負載,因此無法確定概念性流已結束。 這是您的應用程序負責的事情。 檢查標簽或令牌是一種非常簡單的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM