2016-05-02 133 views
1

我寫了一個TcpClient和服務器,它們通過SslStream進行通信。 通信起作用,但是當我從客戶端向服務器發送消息時,首先服務器讀取1個字節,然後在剩下的步驟中進行。例如:我想送「測試」通過客戶端和服務器收到第一個「T」,然後在「EST」SslStream EndRead獲得第一個1字節

下面是客戶端的代碼發送

public void Send(string text) { 
     byte[] message = Encoding.UTF8.GetBytes(text); 
     SecureStream.BeginWrite(message, 0, message.Length, new AsyncCallback(WriteCallback), null); 
    } 

    private void WriteCallback(IAsyncResult AR) { 

    } 

而這裏的代碼服務器用來讀取

private SslStream CryptedStream = ...; 
    private byte[] buffer = new byte[1024]; 

    public void BeginReadCallback(IAsyncResult AsyncCall) { 

     // initialize variables 
     int bytesRead = 0; 

     try { 
      // retrieve packet 
      bytesRead = CryptedStream.EndRead(AsyncCall); 

      // check if client has disconnected 
      if (bytesRead > 0) { 
       // copy buffer to a temporary one 
       var temporaryBuffer = buffer; 
       Array.Resize(ref temporaryBuffer, bytesRead); 

       string read = Encoding.ASCII.GetString(temporaryBuffer); 
       SetText(read); 

       // read more data 
       CryptedStream.BeginRead(buffer, 0, 1024, new AsyncCallback(BeginReadCallback), null); 

       // client is still connected, read data from buffer 
       //ProcessPacket(temporaryBuffer, temporaryBuffer.Length, helper); 
      } else { 
       // client disconnected, do everything to disconnect the client 
       //DisconnectClient(helper); 
      } 
     } catch (Exception e) { 
      // encountered an error, closing connection 
      // Program.log.Add(e.ToString(), Logger.LogLevel.Error); 
      // DisconnectClient(helper); 
     } 
    } 

我錯過了什麼嗎? 感謝您的幫助

+1

這裏有什麼問題? *流式連接*不會以任何方式發送字節數據包,它會發送字節流,因此在閱讀時必須準備好將更小的部分放在一個包中,然後將其重新組合成一個連貫的包。需要。 –

+0

我不熟悉溪流,所以請原諒我缺乏經驗。 所以這可能意味着如果服務器速度更快,我會收到「t」「e」「s」「t」? –

+1

你*可以*收到,或者你可以收到'tes',然後't',或者't',然後'est'或者'te',然後'st'。它取決於很多事情,速度,硬件上的緩衝區(您的計算機,路由器和兩個端點之間的交換機等)以及軟件。總之,你的代碼需要能夠處理這個。 –

回答

1

由於Lasse解釋了流式API不承諾您每次讀取返回特定數量的字節。

最好的解決方法是不使用套接字。使用更高級別的API,例如WCF,SignalR,HTTP,...

如果您堅持要使用BinaryReader/Writer來發送您的數據。這使得它很容易。例如,它有內置的字符串發送。您也可以使用這些類輕鬆地手動設置長度前綴。

也許,您不需要異步IO,也不應該使用它。如果你堅持,你至少可以通過使用await擺脫回調。