基于加密的TCPIP網(wǎng)絡(luò)聊天軟件的設(shè)計與實現(xiàn)_第1頁
基于加密的TCPIP網(wǎng)絡(luò)聊天軟件的設(shè)計與實現(xiàn)_第2頁
基于加密的TCPIP網(wǎng)絡(luò)聊天軟件的設(shè)計與實現(xiàn)_第3頁
基于加密的TCPIP網(wǎng)絡(luò)聊天軟件的設(shè)計與實現(xiàn)_第4頁
基于加密的TCPIP網(wǎng)絡(luò)聊天軟件的設(shè)計與實現(xiàn)_第5頁
已閱讀5頁,還剩11頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、C#網(wǎng)絡(luò)編程課程設(shè)計報告基于加密的TCP/IP網(wǎng)絡(luò)聊天軟件的設(shè)計與實現(xiàn)1緒 論本課題是一個基于加密的TCP/IP網(wǎng)絡(luò)聊天軟件的設(shè)計與實現(xiàn)。通過基于網(wǎng)絡(luò)方面的編程設(shè)計,深入理解C#語言的基礎(chǔ)理論知識,更深刻地領(lǐng)會使用C#實現(xiàn)網(wǎng)絡(luò)編程的精髓!TCP/IP協(xié)議是當(dāng)前廣域網(wǎng)和局域網(wǎng)通用的網(wǎng)絡(luò)協(xié)議,因此,基于TCP/IP的編程就格外重要。從應(yīng)用上來說,現(xiàn)在直接利用C層次Socket API進(jìn)行TCP/IP編程的人確實越來越少了,各種現(xiàn)成的框架(如ACE、Java、.NET FCL)和控件(如IP*Works)大大簡化了TCP/IP編程的難度。但是,如果想要在這個領(lǐng)域達(dá)到融會貫通的地步,不打下堅實的基礎(chǔ)是

2、不可想象的。正如Richard Stevens在TCP/IP Illustrated中所說,在網(wǎng)絡(luò)編程領(lǐng)域,開發(fā)者所遇到的實際問題中,大約有90%都與開發(fā)者對于TCP/IP的理解相關(guān)。高層的框架和控件總結(jié)了TCP/IP的主要使用模式,并且進(jìn)行了抽象和封裝,這固然非常好,但是想要真正掌握TCP/IP網(wǎng)絡(luò)編程的真諦,還得靠自己一不一個腳印從基礎(chǔ)的開始。誠然C#語言的抽象、封裝給我們使用帶來方便,但是我覺得弄清楚其底層實現(xiàn)是非常重要的! 信息化的發(fā)展使得豐富的資源共享,而有的人就喜歡貪得無厭去竊取別人的隱私,所以加密技術(shù)也不斷的發(fā)展。本課題是使用對稱加密算法才加密數(shù)據(jù)。 信息時代計算機技術(shù)的發(fā)展給整

3、個社會的生活、工作方式帶來了一次革命。因此網(wǎng)絡(luò)編程設(shè)計是很有意義的!2 系統(tǒng)原理分析1、 服務(wù)器和客戶端連接基于TCP/IP套接字編程三個步驟:服務(wù)器監(jiān)聽,客戶端請求,連接確認(rèn)。所謂服務(wù)器監(jiān)聽,是服務(wù)器端套接字并不定位具體的客戶端套接字,而是處于等待連接的狀態(tài),實時監(jiān)控網(wǎng)絡(luò)狀態(tài)??蛻舳苏埱?,是指由客戶端的套接字提出連接請求,要連接的目標(biāo)是服務(wù)器端的套接字。為此,客戶端的套接字必須首先描述它要連接的服務(wù)器的套接字,指出服務(wù)器端套接字的地址和端口號,然后就向服務(wù)器端套接字提出連接請求。連接確認(rèn),是指當(dāng)服務(wù)器端套接字監(jiān)聽到或者說接收到客戶端套接字的連接請求,它就響應(yīng)客戶端套接字的請求,建立一個新的線

4、程,把服務(wù)器端套接字的描述發(fā)給客戶端,一旦客戶端確認(rèn)了此描述,連接就建立好了。而服務(wù)器端套接字繼續(xù)處于監(jiān)聽狀態(tài),繼續(xù)接收其他客戶端套接字的連接請求。所以Socket接口的網(wǎng)絡(luò)通訊原理:首先,服務(wù)端有一個進(jìn)程(或多個進(jìn)程)在指定的端口等待客戶來連接,服務(wù)程序等待客戶的連接信息,一旦連接上之后,就可以按設(shè)計的數(shù)據(jù)交換方法和格式進(jìn)行數(shù)據(jù)傳輸。在使用TCP協(xié)議時,一般服務(wù)端進(jìn)程先使用socket調(diào)用得到一個描述符,然后使用bind調(diào)用將一個名字與socket描述符連接起來,對于Internet域就是將Internet地址聯(lián)編到socket。對于實例服務(wù)端用TcpListener監(jiān)聽,然后把連接的對象實

5、例化為一個TcpClient,調(diào)用TcpClient.GetStream()方法,返回網(wǎng)絡(luò)流實例化為一個NetworlStream流,然后進(jìn)行Send,Receive。2、 使用對稱加密傳輸流程分析本程序使用DESCryptoServiceProvider類 實現(xiàn)DES對稱加密運算。服務(wù)器端:首先從客戶端接收共密鑰,然后使用公共密鑰加密未來使用的對稱密鑰,再將加密了的對稱密鑰發(fā)給客戶端,最后才給客戶端發(fā)送加密了的信息!客戶端:首先建立和發(fā)送公共密鑰給服務(wù)器,然后從服務(wù)器接受加密的對稱密鑰,再解密該對稱密鑰將它作為自己私有的不對稱密鑰,最后才接收信息!3 詳細(xì)代碼設(shè)計服務(wù)器端開發(fā)的詳細(xì)代碼:/添

6、加的命名空間引用(原始生成的略)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<User> userList = new List<User>(); private delega

7、te void SetListBoxCallback(string str); private SetListBoxCallback setListBoxCallback; private delegate void SetComboBoxCallback(User user); private SetComboBoxCallback setComboBoxCallback; /使用的本機IP地址 IPAddress localAddress; /監(jiān)聽端口 private int port = 6788;/和書上一樣 private TcpListener myListener; public

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

9、d = false; /開始監(jiān)聽 private void buttonStart_Click(object sender, EventArgs e) myListener = new TcpListener(localAddress, port); myListener.Start(); SetListBox(string.Format("開始在0:1監(jiān)聽客戶連接", localAddress, port); /創(chuàng)建一個線程監(jiān)聽客戶端連接請求 ThreadStart ts = new ThreadStart(ListenClientConnect); Thread myT

10、hread = new Thread(ts); myThread.Start(); buttonStart.Enabled = false; buttonStop.Enabled = true; /接收客戶端連接的線程 private void ListenClientConnect() while (true) TcpClient newClient = null; try /等待用戶進(jìn)入 newClient = myListener.AcceptTcpClient(); catch /當(dāng)單擊“停止監(jiān)聽”或者退出此窗體時AcceptTcpClient()會產(chǎn)生異常,因此可以利用此異常退出循環(huán)

11、 break; /每接受一個客戶端連接,就創(chuàng)建一個對應(yīng)的線程循環(huán)接收該客戶端發(fā)來的信息 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進(jìn)入"

12、;, newClient.Client.RemoteEndPoint); SetListBox(string.Format("當(dāng)前連接用戶數(shù):0", userList.Count); /接收、處理客戶端信息的線程,每客戶1個線程,參數(shù)用于區(qū)分是哪個客戶 private void ReceiveData(object obj) User user = (User)obj; TcpClient client = user.client; /是否正常退出接收線程 bool normalExit = false; /用于控制是否退出循環(huán) bool exitWhile = false

13、; while (exitWhile = false) /保存接收的命令字符串 string receiveString = null; /每條命令均帶有一個參數(shù),值為true或者false,表示是否有緊跟的字節(jié)數(shù)組 string splitString = null; byte receiveBytes = null; try /從網(wǎng)絡(luò)流中讀出命令字符串 /此方法會自動判斷字符串長度前綴,并根據(jù)長度前綴讀出字符串 receiveString = user.br.ReadString(); splitString = receiveString.Split(','); if (

14、splitString1 = "true") /先從網(wǎng)絡(luò)流中讀出32位的長度前綴 int bytesLength = user.br.ReadInt32(); /然后讀出指定長度的內(nèi)容保存到字節(jié)數(shù)組中 receiveBytes = user.br.ReadBytes(bytesLength); catch /底層套接字不存在時會出現(xiàn)異常 SetListBox("接收數(shù)據(jù)失敗"); if (receiveString = null) if (normalExit = false) /如果停止了監(jiān)聽,Connected為false if (client.Co

15、nnected = true) SetListBox(string.Format( "與0失去聯(lián)系,已終止接收該用戶信息", client.Client.RemoteEndPoint); break; SetListBox(string.Format("來自0:1", user.client.Client.RemoteEndPoint, receiveString); if (receiveBytes != null) SetListBox(string.Format("來自0:1", user.client.Client.Remot

16、eEndPoint, Encoding.Default.GetString(receiveBytes); switch (splitString0)/公鑰和私鑰的加密解密實現(xiàn) case "rsaPublicKey": user.rsa.FromXmlString(Encoding.Default.GetString(receiveBytes); /加密對稱加密的私鑰 try byte encryptedKey = user.rsa.Encrypt(user.tdes.Key, false); SendToClient(user, "tdesKey,true&quo

17、t;, encryptedKey); /加密IV byte encryptedIV = user.rsa.Encrypt(user.tdes.IV, false); SendToClient(user, "tdesIV,true", encryptedIV); catch (Exception err) MessageBox.Show(err.Message); break; case "Logout": /格式:Logout SetListBox(string.Format("0退出", user.client.Client.Rem

18、oteEndPoint); normalExit = true; exitWhile = true; break; case "Talk": /解密 string talkString = DecryptText(receiveBytes, user.tdes.Key, user.tdes.IV); if (talkString != null) SetListBox(string.Format("0說:1", client.Client.RemoteEndPoint, talkString); break; default: SetListBox(&q

19、uot;什么意思?。?quot; + receiveString); break; userList.Remove(user); client.Close(); SetListBox(string.Format("當(dāng)前連接用戶數(shù):0", userList.Count); / 對稱加密算法加密數(shù)據(jù)的具體實現(xiàn) private byte EncryptText(string str, byte Key, byte IV) /創(chuàng)建一個內(nèi)存流 MemoryStream memoryStream = new MemoryStream(); /使用傳遞的私鑰和IV創(chuàng)建加密流 Crypto

20、Stream cryptoStream = new CryptoStream(memoryStream, new TripleDESCryptoServiceProvider().CreateEncryptor(Key, IV), CryptoStreamMode.Write); /將傳遞的字符串轉(zhuǎn)換為字節(jié)數(shù)組 byte toEncrypt = Encoding.UTF8.GetBytes(str); try /將字節(jié)數(shù)組寫入加密流,并清除緩沖區(qū) cryptoStream.Write(toEncrypt, 0, toEncrypt.Length); cryptoStream.FlushFina

21、lBlock(); /得到加密后的字節(jié)數(shù)組 byte encryptedBytes = memoryStream.ToArray(); return encryptedBytes; catch (Exception err) SetListBox("加密出錯:" + err.Message); return null; finally cryptoStream.Close(); memoryStream.Close(); /使用對稱加密算法解密接收的數(shù)據(jù) private string DecryptText(byte dataBytes, byte Key, byte IV

22、) /根據(jù)加密后的字節(jié)數(shù)組創(chuàng)建一個內(nèi)存流 MemoryStream memoryStream = new MemoryStream(dataBytes); /使用傳遞的私鑰、IV和內(nèi)存流創(chuàng)建解密流 CryptoStream cryptoStream = new CryptoStream(memoryStream, new TripleDESCryptoServiceProvider().CreateDecryptor(Key, IV), CryptoStreamMode.Read); /創(chuàng)建一個字節(jié)數(shù)組保存解密后的數(shù)據(jù) byte decryptBytes = new bytedataBytes

23、.Length; try /從解密流中將解密后的數(shù)據(jù)讀到字節(jié)數(shù)組中 cryptoStream.Read(decryptBytes, 0, decryptBytes.Length); /得到解密后的字符串 string decryptedString = Encoding.UTF8.GetString(decryptBytes); return decryptedString; catch (Exception err) SetListBox("解密出錯:" + err.Message); return null; finally cryptoStream.Close();

24、memoryStream.Close(); /發(fā)送信息到客戶端 private void SendToClient(User user, string command, byte bytes) /每條命令均帶有一個參數(shù),值為true或者false,表示是否有緊跟的字節(jié)數(shù)組 string splitCommand = command.Split(','); try /先將命令字符串寫入網(wǎng)絡(luò)流,此方法會自動附加字符串長度前綴 user.bw.Write(command); SetListBox(string.Format("向0發(fā)送:1", user.clien

25、t.Client.RemoteEndPoint, command); if (splitCommand1 = "true") /先將字節(jié)數(shù)組的長度(32位整數(shù))寫入網(wǎng)絡(luò)流 user.bw.Write(bytes.Length); /然后將字節(jié)數(shù)組寫入網(wǎng)絡(luò)流 user.bw.Write(bytes); user.bw.Flush(); SetListBox(string.Format("向0發(fā)送:1", user.client.Client.RemoteEndPoint, Encoding.UTF8.GetString(bytes); if (splitC

26、ommand0 = "Talk") SetListBox("加密前內(nèi)容:" + textBoxSend.Text); catch SetListBox(string.Format("向0發(fā)送信息失敗", user.client.Client.RemoteEndPoint); private void AddComboBoxitem(User user) if (comboBoxReceiver.InvokeRequired = true) this.Invoke(setComboBoxCallback, user); else com

27、boBoxReceiver.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()

28、; /單擊停止監(jiān)聽按鈕觸發(fā)的事件 private void buttonStop_Click(object sender, EventArgs e) SetListBox(string.Format("目前連接用戶數(shù):0", userList.Count); SetListBox("開始停止服務(wù),并依次使用戶退出!"); for (int i = 0; i < userList.Count; i+) comboBoxReceiver.Items.Remove(userListi.client.Client.RemoteEndPoint); user

29、Listi.bw.Close(); userListi.br.Close(); userListi.client.Close(); /通過停止監(jiān)聽讓myListener.AcceptTcpClient()產(chǎn)生異常退出監(jiān)聽線程 myListener.Stop(); buttonStart.Enabled = true; buttonStop.Enabled = false; /單擊發(fā)送按鈕的Click事件 private void buttonSend_Click(object sender, EventArgs e) int index = comboBoxReceiver.SelectedI

30、ndex; if (index = -1) MessageBox.Show("請先選擇接收方,然后再單擊發(fā)送"); else User user = (User)userListindex; /加密textBoxSend.Text的內(nèi)容 byte encryptedBytes = EncryptText(textBoxSend.Text, user.tdes.Key, user.tdes.IV); if (encryptedBytes != null) SendToClient(user, "Talk,true", encryptedBytes); textBoxSend.Clear(); private void FormServer_FormClosing(object sender, FormClosingEventArgs e) /未單擊開始監(jiān)聽就直接退出時,myListe

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論