3

这个概念看起来很简单:创建两个独立的应用程序,从客户端向服务器发送加密文本,然后从服务器向客户端发送回复——我假设我可以简单地在两者之间建立一个 TcpClient 连接,获取一个 NetworkStream,并在该 NetworkStream 上使用两个 CryptoStream(一个用于读取,一个用于写入)。但是,在我下面的示例中(主要基于 MSDN 示例),文本可以被加密,发送到服务器,解密并显示得很好,但是当服务器尝试回复时,它会抛出“无法将数据写入交通连接……”。当 StreamWriter 关闭时,底层流可能正在关闭?顺便说一句,当通过 NetworkStream 本身发送未加密的文本时,这个概念非常有效,因为 NetworkStream 本身就是双向的。

编辑:似乎关闭 CryptoStream 会导致其他所有内容也被关闭。如果我在客户端发送消息后在服务器上手动调用 sendReply() ,服务器将成功回复(只要客户端上没有关闭 NetworkStream )。然后服务器将抛出“无法从传输连接读取数据:阻塞操作被对 WSACancelBlockingCall 的调用中断。” 在 SReader.Readline。多个 CryptoStreams 似乎可以工作,所以真正的问题可能是服务器不知道何时停止读取。我也不确定如何补救。在消息中添加“\r\n”并使用 ReadLine() 似乎没有帮助。

服务器:

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 };

Thread listener;
NetworkStream nwStream;
TcpClient client;

RijndaelManaged RMCrypto;
CryptoStream CryptStreamRead;
CryptoStream CryptStreamWrite;
StreamReader SReader;
StreamWriter SWriter;

private void Form1_Load(object sender, EventArgs e)
{
    listener = new Thread(new ThreadStart(tcpListen));
    listener.IsBackground = true;
    listener.Start();
}

private void tcpListen()
{
    int port = 7777;
    string dataReceived;

    TcpListener listener = new TcpListener(IPAddress.Any, port);
    listener.Start();

    while (true)
    {
        client = listener.AcceptTcpClient();
        nwStream = client.GetStream();

        RMCrypto = new RijndaelManaged();
        CryptStreamRead = new CryptoStream(nwStream, RMCrypto.CreateDecryptor(Key, IV), CryptoStreamMode.Read);
        SReader = new StreamReader(CryptStreamRead);

        string received = SReader.ReadLine();
        Invoke(new MethodInvoker(() => textBoxReceived.Text = received));
        Invoke(new MethodInvoker(() => sendReply("REPLY: " + received)));

        //SReader.Close();
        //CryptStreamRead.Close();
        //nwStream.Close();
        //client.Close();

        //listener.Stop();
    }
}

private void sendReply(string input)
{
    try
    {
        CryptStreamWrite = new CryptoStream(nwStream, RMCrypto.CreateEncryptor(Key, IV), CryptoStreamMode.Write);
        SWriter = new StreamWriter(CryptStreamWrite);
        SWriter.WriteLine(input);
        SWriter.Flush();

        SWriter.Close();
        CryptStreamWrite.Close();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }
} 

客户:

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 };

int port = 7777;
string serverIP = "127.0.0.1";
TcpClient client;
NetworkStream nwStream;

RijndaelManaged RMCrypto;
CryptoStream CryptStreamWrite;
CryptoStream CryptStreamRead;
StreamWriter SWriter;
StreamReader SReader;

private void sendToServer(string input)
{
    try
    {
        string textToSend = textBoxToSend.Text;

        client = new TcpClient(serverIP, port);
        nwStream = client.GetStream();
        RMCrypto = new RijndaelManaged();
        //CryptoStream CryptStream = new CryptoStream(nwStream,RMCrypto.CreateEncryptor(Key, IV), CryptoStreamMode.Write);
        CryptStreamWrite = new CryptoStream(nwStream, RMCrypto.CreateEncryptor(Key, IV)), CryptoStreamMode.Write);
        SWriter = new StreamWriter(CryptStreamWrite);
        SWriter.WriteLine(textBoxToSend.Text);
        SWriter.Flush();

        SWriter.Close();
        CryptStreamWrite.Close();
        //nwStream.Close();
        //client.Close();

        waitForResponse();
    }
    catch
    {
        textBoxReceived.Text = "Cannot Create Connection to Server";
    }
}

private void waitForResponse()
{
    try
    {
        CryptStreamRead = new CryptoStream(nwStream, RMCrypto.CreateDecryptor(CalculateMD5Hash(textBoxKey.Text), CalculateMD5Hash(textBoxKey.Text)), CryptoStreamMode.Read);
        SReader = new StreamReader(CryptStreamRead);
        textBoxReceived.Text = SReader.ReadLine();

        SReader.Close();
        CryptStreamRead.Close();
        nwStream.Close();
        client.Close();
    }
    catch
    {
        textBoxReceived.Text = "No Response From Server";
    }
}
4

0 回答 0