2012-04-02 3 views
2

У меня есть базовая настройка клиент/сервер tcp, идущая в C#. Теперь я пытаюсь зашифровать данные, идущие туда и обратно. Я могу отправлять данные от клиента на сервер, сервер запускает команду, а затем пытается отправить результаты обратно клиенту. Я могу получить данные от клиента к серверу, и сервер выполнит команду. Когда сервер пытается отправить результаты обратно клиенту, я получаю сообщение об ошибке на клиенте, что поток не читается. Ниже приведены соответствующие части кода.клиент/сервер, зашифрованные сообщения

Сервер:

....... 
//Create an instance of TcpListener to listen for TCP connection. 
    TcpListener tcpListener = new TcpListener(IPAddress.Any, TcpPort); 
    try 
    { 
     while (true) 
     { 
      tcpListener.Start(); 
      //Accept the client if one is found. 
      TcpClient TCP = tcpListener.AcceptTcpClient(); 
      // Console.WriteLine("Client connected through TCP."); 

      //Create a network stream from the connection. 
      NetworkStream NetStream = TCP.GetStream(); 

      //Create a new instance of the RijndaelManaged class 
      // and decrypt the stream. 
      RijndaelManaged RMCrypto = new RijndaelManaged(); 


      //Create a CryptoStream, pass it the NetworkStream, decrypt with the Rijndael class using the key and IV. 
      CryptoStream CryptStream = new CryptoStream(NetStream,RMCrypto.CreateDecryptor(Key, IV),CryptoStreamMode.Read); 

      //Read the stream. 
      StreamReader SReader = new StreamReader(CryptStream); 

      //run the command received 
      string commandToRun = SReader.ReadToEnd(); 
      string commandOutput = runCommand(commandToRun); 
      Console.WriteLine("output is " + commandOutput); 
     //  SReader.Close(); 

      // now send results back 
      CryptoStream CStream_WRITE = new CryptoStream(NetStream, RMCrypto.CreateEncryptor(Key, IV), CryptoStreamMode.Write); 

      if (CStream_WRITE.CanWrite) 
      { 
       //Create a StreamWriter for easy writing to the network stream. 
       StreamWriter SWriter2 = new StreamWriter(CStream_WRITE); 

       //Write to the stream. 
       SWriter2.Write(commandOutput, commandOutput.Length); 
       Console.WriteLine("writing {0} bytes back ", commandOutput.Length); 
       SWriter2.Flush(); 
       SWriter2.Close(); 
      } 

     //  CStream_WRITE.Close(); 
     //  NetStream.Close(); 
     //  TCP.Close(); 
       tcpListener.Stop(); 

     } // end while 
    } 
    //Catch any exceptions. 
    catch 
    { 
     Console.WriteLine("Server Failed"); 
    } 
} 

А вот клиент: ....... Жирная линия, где я получаю сообщение об ошибке

 //Create a TCP connection to a listening TCP process. 

     TcpClient TCP = new TcpClient(serverName, TCPPORT); 

     //Create a network stream from the TCP connection. 
     NetworkStream NetStream = TCP.GetStream(); 

     //Create a new instance of the RijndaelManaged class 
     // and encrypt the stream. 
     RijndaelManaged RMCrypto = new RijndaelManaged(); 

     byte[] Key = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 }; 
     byte[] IV = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16 }; 

     //Create a CryptoStream, pass it the NetworkStream, and encrypt 
     //it with the Rijndael class. 
     CryptoStream CryptStream = new CryptoStream(NetStream, RMCrypto.CreateEncryptor(Key, IV), CryptoStreamMode.Write); 

     if (CryptStream.CanWrite) 
     { 
      //Create a StreamWriter for easy writing to the network stream. 
      StreamWriter SWriter = new StreamWriter(CryptStream); 

      //Write to the stream. 
      SWriter.WriteLine(theData); 
      SWriter.Flush(); 
      SWriter.Close(); 
     // CryptStream.Close(); 

      //Inform the user that the message was written to the stream. 
      Console.WriteLine("The message was sent."); 
     } 

     // get response 
     **CryptoStream CStreamREAD = new CryptoStream(NetStream, RMCrypto.CreateDecryptor(Key, IV), CryptoStreamMode.Read);** 
     if (CStreamREAD.CanRead) 
     { 
      Console.WriteLine("stream can read\n"); 
      StreamReader SReader = new StreamReader(CStreamREAD); 
      string commandResults = SReader.ReadToEnd(); 
      Console.WriteLine("receiving {0} bytes from server", commandResults.Length); 
      Console.WriteLine("results are " + commandResults) 
+0

Пожалуйста, всегда включайте само сообщение ** ** **. О, и приветствую ... –

ответ

4

Самый простой, и на сегодняшний день безопаснее всего, - это реализовать уже существующий протокол, например SSL. Вы можете использовать класс SslStream для обеспечения безопасности и аутентификации сервера, или вы можете просто переключиться на WCF и вообще не иметь дело с потоками. Here - вопрос о том, как включить SSL для WCF. Что касается только основного учебника WCF, то есть сотни.

Роллинг, вероятно, будет очень неуверенным и подверженным ошибкам.

+0

Хороший совет в целом, но плакат, похоже, делает это для «академических» целей ... –

+0

Кроме того, это просто не ответ на вопрос, используйте комментарии! –

+0

Я подумал об этом, но потом я также видел так много вещей, которые являются «академическими», превращаются в производственное программное обеспечение, поэтому нельзя быть слишком осторожными :) – mfanto

0

StreamWriter.close() также закрывает базовый поток, который закрывает CryptoStream, который закрывает базовый сокет в соответствии с API.

По крайней мере, это моя догадка как опытный разработчик Java :)