この概念は単純に思えます: 2 つの別個のアプリケーションを作成し、暗号化されたテキストをクライアントからサーバーに送信し、サーバーからクライアントに応答を送信します。単純に 2 つのアプリケーション間で TcpClient 接続を確立し、NetworkStream を取得できると仮定しました。その NetworkStream で 2 つの CryptoStreams を使用します (1 つは読み取り用、もう 1 つは書き込み用)。ただし、以下の例 (主に MSDN の例に基づいています) では、テキストを暗号化し、サーバーに送信し、復号化して表示することができますが、サーバーが応答しようとすると、「Unable to write data to theトランスポート接続...」。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";
}
}