基于TCPIP聊天软件的代码设计_第1页
基于TCPIP聊天软件的代码设计_第2页
基于TCPIP聊天软件的代码设计_第3页
基于TCPIP聊天软件的代码设计_第4页
基于TCPIP聊天软件的代码设计_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、基于TCP/IP聊天软件的代码设计服务器端开发的详细代码:/添加的命名空间引用(原始生成的略)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

2、 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;

3、 public FormServer() InitializeComponent(); listBoxStatus.HorizontalScrollbar = true; setListBoxCallback = new SetListBoxCallback(SetListBox); setComboBoxCallback = new SetComboBoxCallback(AddComboBoxitem); IPAddress addrIP = Dns.GetHostAddresses(Dns.GetHostName(); localAddress = addrIP0; buttonStop

4、.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

5、 = 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

6、k; /每接受一个客户端连接,就创建一个对应的线程循环接收该客户端发来的信息 ParameterizedThreadStart pts = new ParameterizedThreadStart(ReceiveData); Thread threadReceive = new Thread(pts); User user = new User(newClient); threadReceive.Start(user); userList.Add(user); AddComboBoxitem(user); SetListBox(string.Format(0进入, newClient.Clie

7、nt.RemoteEndPoint); SetListBox(string.Format(当前连接用户数: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) /

8、保存接收的命令字符串 string receiveString = null; /每条命令均带有一个参数,值为true或者false,表示是否有紧跟的字节数组 string splitString = null; byte receiveBytes = null; try /从网络流中读出命令字符串 /此方法会自动判断字符串长度前缀,并根据长度前缀读出字符串 receiveString = user.br.ReadString(); splitString = receiveString.Split(,); if (splitString1 = true) /先从网络流中读出32位的长度前缀

9、int bytesLength = user.br.ReadInt32(); /然后读出指定长度的内容保存到字节数组中 receiveBytes = user.br.ReadBytes(bytesLength); catch /底层套接字不存在时会出现异常 SetListBox(接收数据失败); if (receiveString = null) if (normalExit = false) /如果停止了监听,Connected为false if (client.Connected = true) SetListBox(string.Format( 与0失去联系,已终止接收该用户信息, cl

10、ient.Client.RemoteEndPoint); break; SetListBox(string.Format(来自0:1, user.client.Client.RemoteEndPoint, receiveString); if (receiveBytes != null) SetListBox(string.Format(来自0:1, user.client.Client.RemoteEndPoint, Encoding.Default.GetString(receiveBytes); switch (splitString0)/公钥和私钥的加密解密实现 case rsaPub

11、licKey: user.rsa.FromXmlString(Encoding.Default.GetString(receiveBytes); /加密对称加密的私钥 try byte encryptedKey = user.rsa.Encrypt(user.tdes.Key, false); SendToClient(user, tdesKey,true, encryptedKey); /加密IV byte encryptedIV = user.rsa.Encrypt(user.tdes.IV, false); SendToClient(user, tdesIV,true, encrypte

12、dIV); catch (Exception err) MessageBox.Show(err.Message); break; case Logout: /格式:Logout SetListBox(string.Format(0退出, user.client.Client.RemoteEndPoint); normalExit = true; exitWhile = true; break; case Talk: /解密 string talkString = DecryptText(receiveBytes, user.tdes.Key, user.tdes.IV); if (talkSt

13、ring != null) SetListBox(string.Format(0说:1, client.Client.RemoteEndPoint, talkString); break; default: SetListBox(什么意思啊: + receiveString); break; userList.Remove(user); client.Close(); SetListBox(string.Format(当前连接用户数:0, userList.Count); / 对称加密算法加密数据的具体实现 private byte EncryptText(string str, byte K

14、ey, byte IV) /创建一个内存流 MemoryStream memoryStream = new MemoryStream(); /使用传递的私钥和IV创建加密流 CryptoStream cryptoStream = new CryptoStream(memoryStream, new TripleDESCryptoServiceProvider().CreateEncryptor(Key, IV), CryptoStreamMode.Write); /将传递的字符串转换为字节数组 byte toEncrypt = Encoding.UTF8.GetBytes(str); try

15、/将字节数组写入加密流,并清除缓冲区 cryptoStream.Write(toEncrypt, 0, toEncrypt.Length); cryptoStream.FlushFinalBlock(); /得到加密后的字节数组 byte encryptedBytes = memoryStream.ToArray(); return encryptedBytes; catch (Exception err) SetListBox(加密出错: + err.Message); return null; finally cryptoStream.Close(); memoryStream.Close

16、(); /使用对称加密算法解密接收的数据 private string DecryptText(byte dataBytes, byte Key, byte IV) /根据加密后的字节数组创建一个内存流 MemoryStream memoryStream = new MemoryStream(dataBytes); /使用传递的私钥、IV和内存流创建解密流 CryptoStream cryptoStream = new CryptoStream(memoryStream, new TripleDESCryptoServiceProvider().CreateDecryptor(Key, IV)

17、, CryptoStreamMode.Read); /创建一个字节数组保存解密后的数据 byte decryptBytes = new bytedataBytes.Length; try /从解密流中将解密后的数据读到字节数组中 cryptoStream.Read(decryptBytes, 0, decryptBytes.Length); /得到解密后的字符串 string decryptedString = Encoding.UTF8.GetString(decryptBytes); return decryptedString; catch (Exception err) SetList

18、Box(解密出错: + err.Message); return null; finally cryptoStream.Close(); memoryStream.Close(); /发送信息到客户端 private void SendToClient(User user, string command, byte bytes) /每条命令均带有一个参数,值为true或者false,表示是否有紧跟的字节数组 string splitCommand = command.Split(,); try /先将命令字符串写入网络流,此方法会自动附加字符串长度前缀 user.bw.Write(comman

19、d); SetListBox(string.Format(向0发送:1, user.client.Client.RemoteEndPoint, command); if (splitCommand1 = true) /先将字节数组的长度(32位整数)写入网络流 user.bw.Write(bytes.Length); /然后将字节数组写入网络流 user.bw.Write(bytes); user.bw.Flush(); SetListBox(string.Format(向0发送:1, user.client.Client.RemoteEndPoint, Encoding.UTF8.GetSt

20、ring(bytes); if (splitCommand0 = Talk) SetListBox(加密前内容: + textBoxSend.Text); catch SetListBox(string.Format(向0发送信息失败, user.client.Client.RemoteEndPoint); private void AddComboBoxitem(User user) if (comboBoxReceiver.InvokeRequired = true) this.Invoke(setComboBoxCallback, user); else comboBoxReceiver

21、.Items.Add(user.client.Client.RemoteEndPoint); private void SetListBox(string str) if (listBoxStatus.InvokeRequired = true) this.Invoke(setListBoxCallback, str); else listBoxStatus.Items.Add(str); listBoxStatus.SelectedIndex = listBoxStatus.Items.Count - 1; listBoxStatus.ClearSelected(); /单击停止监听按钮触发

22、的事件 private void buttonStop_Click(object sender, EventArgs e) SetListBox(string.Format(目前连接用户数:0, userList.Count); SetListBox(开始停止服务,并依次使用户退出!); for (int i = 0; i userList.Count; i+) comboBoxReceiver.Items.Remove(userListi.client.Client.RemoteEndPoint); userListi.bw.Close(); userListi.br.Close(); userListi.client.Close(); /通过停止监听让myListener.AcceptTcpClient()产生异常退出监听线程 myListener.Stop(); buttonStart.Enabled = true; buttonStop.Enabled = false; /单击发送按钮的Click事件 private void buttonSend_Click(object sende

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论