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

下載本文檔

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

文檔簡(jiǎn)介

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

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

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

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

5、例化為一個(gè)TcpClient,調(diào)用TcpClient.GetStream()方法,返回網(wǎng)絡(luò)流實(shí)例化為一個(gè)NetworlStream流,然后進(jìn)行Send,Receive。2、 使用對(duì)稱加密傳輸流程分析本程序使用DESCryptoServiceProvider類 實(shí)現(xiàn)DES對(duì)稱加密運(yùn)算。服務(wù)器端:首先從客戶端接收共密鑰,然后使用公共密鑰加密未來(lái)使用的對(duì)稱密鑰,再將加密了的對(duì)稱密鑰發(fā)給客戶端,最后才給客戶端發(fā)送加密了的信息!客戶端:首先建立和發(fā)送公共密鑰給服務(wù)器,然后從服務(wù)器接受加密的對(duì)稱密鑰,再解密該對(duì)稱密鑰將它作為自己私有的不對(duì)稱密鑰,最后才接收信息!3 詳細(xì)代碼設(shè)計(jì)服務(wù)器端開(kāi)發(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; /使用的本機(jī)IP地址 IPAddress localAddress; /監(jiān)聽(tīng)端口 private int port = 6788;/和書(shū)上一樣 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; /開(kāi)始監(jiān)聽(tīng) private void buttonStart_Click(object sender, EventArgs e) myListener = new TcpListener(localAddress, port); myListener.Start(); SetListBox(string.Format("開(kāi)始在0:1監(jiān)聽(tīng)客戶連接", localAddress, port); /創(chuàng)建一個(gè)線程監(jiān)聽(tīng)客戶端連接請(qǐng)求 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)聽(tīng)”或者退出此窗體時(shí)AcceptTcpClient()會(huì)產(chǎn)生異常,因此可以利用此異常退出循環(huán)

11、 break; /每接受一個(gè)客戶端連接,就創(chuàng)建一個(gè)對(duì)應(yīng)的線程循環(huán)接收該客戶端發(fā)來(lái)的信息 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個(gè)線程,參數(shù)用于區(qū)分是哪個(gè)客戶 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; /每條命令均帶有一個(gè)參數(shù),值為true或者false,表示是否有緊跟的字節(jié)數(shù)組 string splitString = null; byte receiveBytes = null; try /從網(wǎng)絡(luò)流中讀出命令字符串 /此方法會(huì)自動(dòng)判斷字符串長(zhǎng)度前綴,并根據(jù)長(zhǎng)度前綴讀出字符串 receiveString = user.br.ReadString(); splitString = receiveString.Split(','); if (

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

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

16、eEndPoint, Encoding.Default.GetString(receiveBytes); switch (splitString0)/公鑰和私鑰的加密解密實(shí)現(xiàn) case "rsaPublicKey": user.rsa.FromXmlString(Encoding.Default.GetString(receiveBytes); /加密對(duì)稱加密的私鑰 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說(shuō):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); / 對(duì)稱加密算法加密數(shù)據(jù)的具體實(shí)現(xiàn) private byte EncryptText(string str, byte Key, byte IV) /創(chuàng)建一個(gè)內(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("加密出錯(cuò):" + err.Message); return null; finally cryptoStream.Close(); memoryStream.Close(); /使用對(duì)稱加密算法解密接收的數(shù)據(jù) private string DecryptText(byte dataBytes, byte Key, byte IV

22、) /根據(jù)加密后的字節(jié)數(shù)組創(chuàng)建一個(gè)內(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)建一個(gè)字節(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("解密出錯(cuò):" + err.Message); return null; finally cryptoStream.Close();

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

25、t.Client.RemoteEndPoint, command); if (splitCommand1 = "true") /先將字節(jié)數(shù)組的長(zhǎng)度(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)聽(tīng)按鈕觸發(fā)的事件 private void buttonStop_Click(object sender, EventArgs e) SetListBox(string.Format("目前連接用戶數(shù):0", userList.Count); SetListBox("開(kāi)始停止服務(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(); /通過(guò)停止監(jiān)聽(tīng)讓myListener.AcceptTcpClient()產(chǎn)生異常退出監(jiān)聽(tīng)線程 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("請(qǐng)先選擇接收方,然后再單擊發(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) /未單擊開(kāi)始監(jiān)聽(tīng)就直接退出時(shí),myListe

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論