1、对于实例服务端用TcpListener监听,然后把连接的对象实例化为一个TcpClient,调用TcpClient.GetStream()方法,返回网络流实例化为一个NetworlStream流,然后进行Send,Receive。2、 使用对称加密传输流程分析本程序使用DESCryptoServiceProvider类 实现DES对称加密运算。服务器端:首先从客户端接收共密钥,然后使用公共密钥加密未来使用的对称密钥,再将加密了的对称密钥发给客户端,最后才给客户端发送加密了的信息!客户端:首先建立和发送公共密钥给服务器,然后从服务器接受加密的对称密钥,再解密该对称密钥将它作为自己私有的不对称密钥
2、,最后才接收信息!3 详细代码设计服务器端开发的详细代码:/添加的命名空间引用(原始生成的略)using System.Net;using System.Net.Sockets;using System.Threading;using System.IO;using System.Security.Cryptography;namespace EncryptedTcpServer public partial class FormServer : Form /连接的用户 System.Collections.Generic.List userList = new List(); private
3、 delegate void SetListBoxCallback(string str); private SetListBoxCallback setListBoxCallback; private delegate void SetComboBoxCallback(User user); private SetComboBoxCallback setComboBoxCallback; /使用的本机IP地址 IPAddress localAddress; /监听端口 private int port = 6788;/和书上一样 private TcpListener myListener;
4、 public FormServer() InitializeComponent(); listBoxStatus.HorizontalScrollbar = true; setListBoxCallback = new SetListBoxCallback(SetListBox); setComboBoxCallback = new SetComboBoxCallback(AddComboBoxitem); IPAddress addrIP = Dns.GetHostAddresses(Dns.GetHostName(); localAddress = addrIP0; buttonStop
5、.Enabled = false; /开始监听 private void buttonStart_Click(object sender, EventArgs e) myListener = new TcpListener(localAddress, port); myListener.Start(); SetListBox(string.Format(开始在0:1监听客户连接, localAddress, port); /创建一个线程监听客户端连接请求 ThreadStart ts = new ThreadStart(ListenClientConnect); Thread myThread
6、 = new Thread(ts); myThread.Start(); buttonStart.Enabled = false; buttonStop.Enabled = true; /接收客户端连接的线程 private void ListenClientConnect() while (true) TcpClient newClient = null; try /等待用户进入 newClient = myListener.AcceptTcpClient(); catch /当单击“停止监听”或者退出此窗体时AcceptTcpClient()会产生异常,因此可以利用此异常退出循环 brea
7、k; /每接受一个客户端连接,就创建一个对应的线程循环接收该客户端发来的信息 ParameterizedThreadStart pts = new ParameterizedThreadStart(ReceiveData); Thread threadReceive = new Thread(pts); User user = new User(newClient); threadReceive.Start(user); userList.Add(user); AddComboBoxitem(user);0进入, newClient.Client.RemoteEndPoint);当前连接用户数
8、:0, userList.Count); /接收、处理客户端信息的线程,每客户1个线程,参数用于区分是哪个客户 private void ReceiveData(object obj) User user = (User)obj; TcpClient client = user.client; /是否正常退出接收线程 bool normalExit = false; /用于控制是否退出循环 bool exitWhile = false; while (exitWhile = false) /保存接收的命令字符串 string receiveString = null; /每条命令均带有一个参数
9、,值为true或者false,表示是否有紧跟的字节数组 string splitString = null; byte receiveBytes = null; /从网络流中读出命令字符串 /此方法会自动判断字符串长度前缀,并根据长度前缀读出字符串 receiveString = user.br.ReadString(); splitString = receiveString.Split(,); if (splitString1 = true) /先从网络流中读出32位的长度前缀 int bytesLength = user.br.ReadInt32(); /然后读出指定长度的内容保存到字节
10、数组中 receiveBytes = user.br.ReadBytes(bytesLength); /底层套接字不存在时会出现异常 SetListBox(接收数据失败 if (receiveString = null) if (normalExit = false) /如果停止了监听,Connected为false if (client.Connected = true) SetListBox(string.Format( 与0失去联系,已终止接收该用户信息, client.Client.RemoteEndPoint);来自0:1, user.client.Client.RemoteEndP
11、oint, receiveString); if (receiveBytes != null), user.client.Client.RemoteEndPoint, Encoding.Default.GetString(receiveBytes); switch (splitString0)/公钥和私钥的加密解密实现 case rsaPublicKey: user.rsa.FromXmlString(Encoding.Default.GetString(receiveBytes); /加密对称加密的私钥 byte encryptedKey = user.rsa.Encrypt(user.td
12、es.Key, false); SendToClient(user, tdesKey,true, encryptedKey); /加密IV byte encryptedIV = user.rsa.Encrypt(user.tdes.IV, false);tdesIV,true, encryptedIV); catch (Exception err) MessageBox.Show(err.Message);Logout /格式:Logout0退出, user.client.Client.RemoteEndPoint); normalExit = true; exitWhile = true;T
13、alk /解密 string talkString = DecryptText(receiveBytes, user.tdes.Key, user.tdes.IV); if (talkString !0说:, client.Client.RemoteEndPoint, talkString); default:什么意思啊: + receiveString); userList.Remove(user); client.Close();/ 对称加密算法加密数据的具体实现 private byte EncryptText(string str, byte Key, byte IV) /创建一个内存
14、流 MemoryStream memoryStream = new MemoryStream(); /使用传递的私钥和IV创建加密流 CryptoStream cryptoStream = new CryptoStream(memoryStream, new TripleDESCryptoServiceProvider().CreateEncryptor(Key, IV), CryptoStreamMode.Write); /将传递的字符串转换为字节数组 byte toEncrypt = Encoding.UTF8.GetBytes(str); /将字节数组写入加密流,并清除缓冲区 crypt
15、oStream.Write(toEncrypt, 0, toEncrypt.Length); cryptoStream.FlushFinalBlock(); /得到加密后的字节数组 byte encryptedBytes = memoryStream.ToArray(); return encryptedBytes;加密出错: + err.Message); return null; finally cryptoStream.Close(); memoryStream.Close(); /使用对称加密算法解密接收的数据 private string DecryptText(byte dataB
16、ytes, byte Key, byte IV) /根据加密后的字节数组创建一个内存流 MemoryStream memoryStream = new MemoryStream(dataBytes); /使用传递的私钥、IV和内存流创建解密流 new TripleDESCryptoServiceProvider().CreateDecryptor(Key, IV), CryptoStreamMode.Read); /创建一个字节数组保存解密后的数据 byte decryptBytes = new bytedataBytes.Length; /从解密流中将解密后的数据读到字节数组中 crypto
17、Stream.Read(decryptBytes, 0, decryptBytes.Length); /得到解密后的字符串 string decryptedString = Encoding.UTF8.GetString(decryptBytes); return decryptedString;解密出错: /发送信息到客户端 private void SendToClient(User user, string command, byte bytes) string splitCommand = command.Split( /先将命令字符串写入网络流,此方法会自动附加字符串长度前缀 use
18、r.bw.Write(command);向0发送:, user.client.Client.RemoteEndPoint, command); if (splitCommand1 = /先将字节数组的长度(32位整数)写入网络流 user.bw.Write(bytes.Length); /然后将字节数组写入网络流 user.bw.Write(bytes); user.bw.Flush(); user.client.Client.RemoteEndPoint, Encoding.UTF8.GetString(bytes); if (splitCommand0 = 加密前内容: + textBox
19、Send.Text);向0发送信息失败 private void AddComboBoxitem(User user) if (comboBoxReceiver.InvokeRequired = true) this.Invoke(setComboBoxCallback, user); else comboBoxReceiver.Items.Add(user.client.Client.RemoteEndPoint); private void SetListBox(string str) if (listBoxStatus.InvokeRequired = true) this.Invoke
20、(setListBoxCallback, str); listBoxStatus.Items.Add(str); listBoxStatus.SelectedIndex = listBoxStatus.Items.Count - 1; listBoxStatus.ClearSelected(); /单击停止监听按钮触发的事件 private void buttonStop_Click(object sender, EventArgs e)目前连接用户数:开始停止服务,并依次使用户退出! for (int i = 0; i userList.Count; i+) comboBoxReceiver
21、.Items.Remove(userListi.client.Client.RemoteEndPoint); userListi.bw.Close(); userListi.br.Close(); userListi.client.Close(); /通过停止监听让myListener.AcceptTcpClient()产生异常退出监听线程 myListener.Stop(); buttonStart.Enabled = true; /单击发送按钮的Click事件 private void buttonSend_Click(object sender, EventArgs e) int ind
22、ex = comboBoxReceiver.SelectedIndex; if (index = -1) MessageBox.Show(请先选择接收方,然后再单击发送 User user = (User)userListindex; /加密textBoxSend.Text的内容 byte encryptedBytes = EncryptText(textBoxSend.Text, user.tdes.Key, user.tdes.IV); if (encryptedBytes !Talk,true, encryptedBytes); textBoxSend.Clear(); private void FormServer_FormClosing(object sender, FormClosingEventArgs e) /未单击开始监听就直接退出时,myListener为null if (myListener ! buttonStop_Click(null, null); /textBoxSend获得焦点并释放按键后触发的事件 private void textBoxSend_KeyPres
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1