2016-05-02 89 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摆脱回调。