![](https://static.zsdocx.com/FlexPaper/FileRoot/2019-6/5/21/2bc99aec-ecc8-4554-83e8-7c4ac8dbf967/2bc99aec-ecc8-4554-83e8-7c4ac8dbf967pic.jpg)
![用vc++簡(jiǎn)單的多線程聊天室課程設(shè)計(jì)_第1頁(yè)](https://static.zsdocx.com/FlexPaper/FileRoot/2019-6/5/21/2bc99aec-ecc8-4554-83e8-7c4ac8dbf967/2bc99aec-ecc8-4554-83e8-7c4ac8dbf9671.gif)
版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、<p><b> 課 程 設(shè) 計(jì) 書(shū)</b></p><p> 學(xué)院 計(jì)算機(jī)學(xué)院 </p><p> 專(zhuān)業(yè) 計(jì)算機(jī)科學(xué)與技術(shù) </p><p> 班級(jí) </p><p> 題目 局域網(wǎng)聊天室程序
2、 </p><p> 教師 </p><p> 學(xué)生 </p><p><b> 課程設(shè)計(jì)任務(wù)書(shū)</b></p><p><b> 目錄</b></p><p><b&
3、gt; 摘 要2</b></p><p><b> 1 引 言3</b></p><p> 1.1課題背景及意義3</p><p> 1.2 實(shí)驗(yàn)平臺(tái)介紹3</p><p> 1.3 可行性分析3</p><p><b> 2需求分析5</b
4、></p><p> 2.1 設(shè)計(jì)目的5</p><p> 2.2 設(shè)計(jì)要求5</p><p> 2.3 功能要求5</p><p> 2.4 系統(tǒng)主要功能和主要功能描述5</p><p><b> 3設(shè)計(jì)流程圖7</b></p><p> 4
5、調(diào)試分析過(guò)程描述9</p><p><b> 5核心代碼16</b></p><p><b> 5.1服務(wù)端16</b></p><p><b> 5.2客服端21</b></p><p> 6 設(shè)計(jì)的總結(jié)和體會(huì)24</p><p>&
6、lt;b> 7 參考文獻(xiàn)24</b></p><p><b> 局域網(wǎng)聊天室程序</b></p><p><b> 摘 要</b></p><p> 計(jì)算機(jī)網(wǎng)絡(luò)技術(shù)發(fā)展至今已經(jīng)大大超越了人們當(dāng)初的預(yù)想,無(wú)論是人們?nèi)粘5墓ぷ鬟€是學(xué)習(xí),我們都越來(lái)越多的依靠到互聯(lián)網(wǎng)。各種實(shí)時(shí)性的聊天娛樂(lè)軟件也同時(shí)誕
7、生,而且為我們的即時(shí)通訊帶來(lái)了眾多的方便,比如說(shuō)大家所熟知的騰訊QQ、微軟的MSN、移動(dòng)的Fetion等,都是做的比較成功的實(shí)時(shí)聊天工具。隨著網(wǎng)絡(luò)的日益普及,各種聊天工具也層出不窮,但當(dāng)我們學(xué)習(xí)了《windows程序設(shè)計(jì)》這門(mén)課程之后,我們決定設(shè)計(jì)一個(gè)簡(jiǎn)單的聊天系統(tǒng)來(lái)鞏固我們的學(xué)習(xí)。接下來(lái)的課程設(shè)計(jì)就是針對(duì)一個(gè)簡(jiǎn)單的網(wǎng)絡(luò)聊天程序,利用MFC為開(kāi)發(fā)工具,實(shí)現(xiàn)基本的通訊功能。在課程設(shè)計(jì)中,系統(tǒng)開(kāi)發(fā)平臺(tái)為Windows XP,程序設(shè)計(jì)設(shè)計(jì)語(yǔ)言
8、采用Visual C++,數(shù)據(jù)庫(kù)采用Access,程序運(yùn)行平臺(tái)為Windows 98/2000/XP。</p><p> 關(guān)鍵詞 聊天軟件;局域網(wǎng);MFC; Visual C++;多線程</p><p><b> 1 引 言</b></p><p> 1.1課題背景及意義</p><p> 當(dāng)今世界正處于信息
9、時(shí)代,計(jì)算機(jī)和通信網(wǎng)絡(luò)是這一時(shí)代所謂“信息基礎(chǔ)設(shè)施”。在互聯(lián)網(wǎng)相當(dāng)普及的今天,在互聯(lián)網(wǎng)上聊天對(duì)很多“網(wǎng)蟲(chóng)”來(lái)說(shuō)已經(jīng)是家常便飯了。聊天室程序可以說(shuō)是網(wǎng)上最簡(jiǎn)單的多點(diǎn)通信程序。一個(gè)簡(jiǎn)單的聊天室, 從程序員的觀點(diǎn)來(lái)看就是在多個(gè)I/O端點(diǎn)之間實(shí)現(xiàn)多對(duì)多的通信。基于SOCKET的局域網(wǎng)通信是一種靈活的、易于實(shí)現(xiàn)的、低成本的方法。它可以運(yùn)行在各種使用TCP/IP協(xié)議作為通訊協(xié)議的網(wǎng)絡(luò)上。而在SOCKET API的幫助下,開(kāi)發(fā)基于SOCKET的局域網(wǎng)
10、通信軟件也是易于實(shí)現(xiàn)的。</p><p> 1.2 實(shí)驗(yàn)平臺(tái)介紹</p><p> Visual C++(簡(jiǎn)稱(chēng)VC)是Microsoft公司推出的目前使用極為廣泛的基于Windows平臺(tái)的C++可視化開(kāi)發(fā)環(huán)境。VC基于C,C++語(yǔ)言,主要由是MFC組成,是與系統(tǒng)聯(lián)系非常緊密的編程工具,它兼有高級(jí),和低級(jí)語(yǔ)言的雙重性,功能強(qiáng)大,靈活,執(zhí)行效率高,幾乎可說(shuō)VC在 Windows平
11、臺(tái)無(wú)所不能。VC主要是針對(duì)Windows系統(tǒng),適合一些系統(tǒng)級(jí) 的開(kāi)發(fā),可以方便實(shí)現(xiàn)一些底層 的調(diào)用。在VC里邊嵌入?yún)R編語(yǔ)言很簡(jiǎn)單。當(dāng)對(duì)系統(tǒng)性能要求很高的時(shí)候,可用VC開(kāi)發(fā)。VC在多線程、網(wǎng)絡(luò)通信、分布應(yīng)用方面,有著不可比擬的優(yōu)勢(shì)。</p><p><b> 1.3 可行性分析</b></p><p> 本課程設(shè)計(jì)主要解決在客戶(hù)端于客戶(hù)端的信息交換和客戶(hù)
12、端于服務(wù)器的信息交換及服務(wù)器的信息處理上的管理的課程設(shè)計(jì)。</p><p> 此程序主要分為兩部分:服務(wù)器端和客戶(hù)端。服務(wù)器端用于提供一個(gè)網(wǎng)絡(luò)端口,等待客戶(hù)端發(fā)出請(qǐng)求,登錄到此服務(wù)端,然后進(jìn)行網(wǎng)絡(luò)通訊和消息的轉(zhuǎn)發(fā);客戶(hù)端可通過(guò)服務(wù)器端的IP地址發(fā)送連接請(qǐng)求,然后登陸聊天室。在服務(wù)器端的成員列表欄中會(huì)顯示在線的所有人名單,有人退出聊天室,成員列表會(huì)自動(dòng)除名。服務(wù)器端同時(shí)也提供了成員之間的私聊功能,此時(shí)服務(wù)器端作為
13、一個(gè)轉(zhuǎn)發(fā)站,進(jìn)行消息的轉(zhuǎn)發(fā)。整個(gè)程序的主體使用了CSocket類(lèi)的方法,實(shí)現(xiàn)了網(wǎng)絡(luò)通訊聊天。</p><p> 先啟動(dòng)服務(wù)器端聊天程序,這是聊天服務(wù)器需要指定一個(gè)端口號(hào),客戶(hù)端則根據(jù)這個(gè)端口號(hào)以及服務(wù)器的網(wǎng)絡(luò)地址與服務(wù)器進(jìn)行通信。在這里,把端口號(hào)成為“聊天頻道” 。</p><p> 在后面的程序代碼分析中將看到,端口號(hào)并不等同于聊天頻道,而是在聊天頻道上增加一個(gè)固定的偏移值,使得這個(gè)
14、聊天頻道不會(huì)和系統(tǒng)保留的端口發(fā)生沖突。</p><p> 服務(wù)器啟動(dòng)后將在這個(gè)指定的端口號(hào)中等待客戶(hù)的連接。對(duì)于公共聊天室,服務(wù)器對(duì)客戶(hù)的數(shù)目不做任何限制。而對(duì)于私人聊天室,每個(gè)聊天頻道則只能允許兩個(gè)客戶(hù)互相連接,使得一方發(fā)送的信息只能到達(dá)對(duì)方的主機(jī)中。這里的服務(wù)器提供的是公共聊天服務(wù)。</p><p> 通過(guò)分析發(fā)現(xiàn),該程序完全可以通過(guò)Visual C++中MFC完成。</p&
15、gt;<p><b> 2需求分析</b></p><p><b> 2.1 設(shè)計(jì)目的</b></p><p> 綜合運(yùn)用本課程及計(jì)算機(jī)網(wǎng)絡(luò)的相關(guān)知識(shí)設(shè)計(jì)并實(shí)現(xiàn)一個(gè)網(wǎng)絡(luò)應(yīng)用程序,以Visual C++作為開(kāi)發(fā)平臺(tái),通過(guò)實(shí)踐復(fù)習(xí)鞏固課堂所學(xué)的理論知識(shí),提高對(duì)所學(xué)知識(shí)的綜合應(yīng)用能力。</p><p><
16、;b> 2.2 設(shè)計(jì)要求</b></p><p> 采用客戶(hù)/服務(wù)器模式,分為客戶(hù)端程序和服務(wù)器端程序。服務(wù)器采用WINSOCK I/O模型中的任一種,支持多個(gè)客戶(hù)同時(shí)在線聊天??蛻?hù)端程序和服務(wù)器程序通過(guò)網(wǎng)絡(luò)交換聊天字符串內(nèi)容,服務(wù)器窗口的列表框中顯示當(dāng)前在線用戶(hù),支持客戶(hù)端之間的私聊(可以通過(guò)服務(wù)器中轉(zhuǎn),或考慮UDP打洞直接建立端端連接)。</p><p> 課程
17、設(shè)計(jì)要求設(shè)計(jì)并編程完成兩個(gè)方面的內(nèi)容:首先建立一個(gè)使用TCP協(xié)議的聊天室服務(wù)器,這個(gè)服務(wù)器可以同時(shí)支持多個(gè)用戶(hù)的在線聊天;其次設(shè)計(jì)一個(gè)可以和服務(wù)器通信的聊天室客戶(hù)端。</p><p><b> 2.3 功能要求</b></p><p> 支持多個(gè)客戶(hù)端的連接,在服務(wù)器和多個(gè)客戶(hù)端之間進(jìn)行數(shù)據(jù)傳輸;</p><p> 接收客戶(hù)端發(fā)送的消息,
18、并顯示在一個(gè)列表框中;</p><p> 在用戶(hù)連接上后有提示,顯示出連接的用戶(hù)名字;</p><p> 發(fā)送信息時(shí)可以顯示聊天的所有記錄;</p><p> 2.4 系統(tǒng)主要功能和主要功能描述</p><p> 服務(wù)器端聊天程序必須能夠做3件事情:</p><p> 服務(wù)器聊天程序要在待定的端口上等待來(lái)自聊
19、天客戶(hù)的連接請(qǐng)求,并且需要維護(hù)一個(gè)客戶(hù)連接表,以記錄所有成功的連接。</p><p> 服務(wù)器聊天程序要及時(shí)接受從各個(gè)聊天客戶(hù)發(fā)送過(guò)來(lái)的信息,然后把這些信息轉(zhuǎn)發(fā)到一個(gè)或多個(gè)客戶(hù)連接。對(duì)于公共聊天室,服務(wù)器將把接受到的信息向除源端外的所有客戶(hù)發(fā)送過(guò)去。</p><p> 服務(wù)器還要監(jiān)控這些連接的狀態(tài),在客戶(hù)主動(dòng)離開(kāi)或發(fā)生故障時(shí)從列表中刪除相應(yīng)的表項(xiàng),并及時(shí)更新連接表。</p>
20、<p> 客戶(hù)端聊天程序需要完成以下幾個(gè)功能:</p><p> 客戶(hù)端聊天程序要負(fù)責(zé)建立和維護(hù)與服務(wù)器的連接,通過(guò)獲取用戶(hù)的設(shè)置嘗試與服務(wù)器的連接,并且隨時(shí)檢測(cè)連接的狀態(tài)。</p><p> 客戶(hù)端聊天程序要把用戶(hù)輸入的信息及時(shí)發(fā)送到聊天服務(wù)器。一般情況下,當(dāng)用戶(hù)輸入一行信息并且按下回車(chē)鍵后聊天程序就要把這一行信息發(fā)送出去,才能及時(shí)地滿(mǎn)足用戶(hù)的交互需求。</p&
21、gt;<p> 要隨時(shí)準(zhǔn)備好接受來(lái)自服務(wù)器的信息,隨時(shí)把接受到的信息顯示出來(lái),讓用戶(hù)及時(shí)看到對(duì)方的響應(yīng)。</p><p> 在用戶(hù)退出聊天過(guò)程是要關(guān)閉與服務(wù)器的連接。比較好的做法是提前通知服務(wù)器或者直接給服務(wù)器發(fā)送一條退出通知,使得服務(wù)器能夠及時(shí)掌握客戶(hù)端的連接狀態(tài),把對(duì)方客戶(hù)的退出信息及時(shí)發(fā)送到對(duì)等實(shí)體上。</p><p><b> 3設(shè)計(jì)流程圖</b
22、></p><p> 根據(jù)對(duì)用戶(hù)的要求及功能設(shè)置可以得到以下的流程圖3.1,用戶(hù)首先啟動(dòng)客戶(hù)端,登陸服務(wù)器并向服務(wù)器發(fā)送信息,啟動(dòng)服務(wù)器,服務(wù)器等待客戶(hù)要求并向客戶(hù)反饋在線用戶(hù)信息,用戶(hù)向服務(wù)器發(fā)送信息,服務(wù)器處理用戶(hù)的數(shù)據(jù),然后用戶(hù)開(kāi)始聊天。客戶(hù)端的聊天分為對(duì)所有人的信息和私聊的信息,該信息應(yīng)通過(guò)程序控制分別進(jìn)行處理。</p><p> 圖3.1 設(shè)計(jì)流程圖</p>
23、<p> 4 調(diào)試分析過(guò)程描述</p><p> 在聊天客服端啟動(dòng)的時(shí)候?qū)Χ丝谶M(jìn)行監(jiān)聽(tīng),會(huì)出現(xiàn)圖4.1的界面。</p><p> 圖4.1登陸服務(wù)器界面</p><p> 在客戶(hù)端啟動(dòng)的時(shí)候,會(huì)出現(xiàn)圖4.2的界面,該界面為客戶(hù)端的連接界面。</p><p> 圖4.2 登陸客戶(hù)端界面(客服端1)</p>
24、<p> 圖4.2 登陸客戶(hù)端界面(客服端2)</p><p> 圖4.3為用戶(hù)張三和李四連接服務(wù)器時(shí)的界面</p><p> 圖4.3 張三登陸服務(wù)器</p><p> 圖4.3李四登陸服務(wù)器</p><p> 圖4.4為用戶(hù)李四發(fā)送消息的服務(wù)器界面</p><p> 圖4.4 李四發(fā)送消息服務(wù)
25、端界面</p><p> 圖4.5為用戶(hù)張三發(fā)送消息的服務(wù)器界面</p><p> 圖4.4 張三發(fā)送消息服務(wù)端界面</p><p> 圖4.6為用戶(hù)李四發(fā)送消息的客服端界面</p><p> 圖4.6李四發(fā)送消息的客服端界面</p><p> 圖4.7為用戶(hù)張三發(fā)送消息的客服端界面</p>&
26、lt;p> 圖4.7張三發(fā)送消息的客服端界面</p><p><b> 5核心代碼</b></p><p><b> 5.1服務(wù)端</b></p><p><b> (1).啟動(dòng)監(jiān)聽(tīng)</b></p><p> UpdateData(TRUE);//更新數(shù)據(jù)到類(lèi)
27、成員</p><p> GetDlgItem(IDC_BTNSTART)->EnableWindow(FALSE);</p><p> GetDlgItem(IDC_BTNSEND)->EnableWindow(TRUE);</p><p> g_ServerSocket=socket(AF_INET,SOCK_STREAM,0); //創(chuàng)建套接
28、字</p><p> if( INVALID_SOCKET == g_ServerSocket)</p><p><b> {</b></p><p> MessageBox("創(chuàng)建套接字失??!");</p><p><b> return ;</b></p>
29、<p><b> }</b></p><p> SOCKADDR_IN svraddrsock;</p><p> svraddrsock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);</p><p> svraddrsock.sin_family=AF_INET;</p>
30、<p> svraddrsock.sin_port=htons(m_port);</p><p> if ( SOCKET_ERROR == bind(g_ServerSocket,(SOCKADDR*)&svraddrsock,sizeof(SOCKADDR)))</p><p><b> {</b></p><p>
31、; MessageBox("套接字綁定失?。?quot;);</p><p> return ;</p><p><b> }</b></p><p> listen(g_ServerSocket,10);//監(jiān)聽(tīng)套接字</p><p><b> //創(chuàng)建接收線程</b>&
32、lt;/p><p> m_hAcceptthread=CreateThread(NULL,0,AcceptThread,NULL,0,NULL);</p><p> if (m_hAcceptthread ==NULL)</p><p><b> {</b></p><p> MessageBox("創(chuàng)建接
33、收連接線程失敗!");</p><p><b> return ;</b></p><p><b> }</b></p><p> g_hmutex=CreateMutex(NULL,FALSE,NULL); //創(chuàng)建互斥量</p><p> (2).監(jiān)聽(tīng)請(qǐng)求連接線程</p
34、><p><b> //接收連接</b></p><p> DWORD WINAPI AcceptThread( LPVOID lpParameter)</p><p><b> {</b></p><p> SOCKADDR_IN serveraddr;</p><p>
35、; int addrlen=sizeof(SOCKADDR);</p><p> SOCKET RecvSocket;//recv后返回的套接字</p><p> RecvSocket=accept(g_ServerSocket,(SOCKADDR *)&serveraddr,&addrlen);</p><p> g_ClientSocke
36、t = RecvSocket;</p><p> if ( INVALID_SOCKET==RecvSocket)</p><p><b> {</b></p><p> AfxMessageBox("接受連接失敗!");</p><p> return FALSE;</p>&
37、lt;p><b> }</b></p><p> BOOL ContinueFlag=TRUE;</p><p> while (ContinueFlag&&TRUE)</p><p><b> {</b></p><p> g_Mutex.Lock();</
38、p><p> BYTE recvBuff[RECV_DATA_SIZE + 2]={0};</p><p> int recvlength=sizeof(recvBuff);</p><p> int recvedSize = 0;</p><p> recvedSize = recv(RecvSocket,(char*)recvB
39、uff,recvlength,0);</p><p> if(SOCKET_ERROR == recvedSize)</p><p><b> {</b></p><p> int x=WSAGetLastError();</p><p> CString str;</p><p> /
40、/WSANOTINITIALISED</p><p> str.Format("錯(cuò)誤代碼:%d", x);</p><p> AfxMessageBox(str);</p><p><b> break ;</b></p><p><b> }</b></p>
41、<p> CStringArray RecvData;</p><p> UINT CmdFlag;</p><p> CChatRoomServerDlg::Split((char*)recvBuff,'|',RecvData); //將收到的數(shù)據(jù)進(jìn)行分離</p><p> if (RecvData.GetSize()&l
42、t;=0)</p><p><b> {</b></p><p> continue ;</p><p><b> }</b></p><p> CmdFlag=atoi(RecvData.GetAt(0).GetBuffer(RecvData.GetAt(0).GetLength()));
43、</p><p> int i=0; //記錄循環(huán)次數(shù)的變量</p><p> BOOL comeFlag=TRUE ;//是否加入用戶(hù)列表的標(biāo)記</p><p> CTime iotime;</p><p> CString StrRecord=""; //聊天內(nèi)容</p><p>
44、CString strTemp="";</p><p> CString strTemp1="";</p><p> char sendBuff[1024]={0};</p><p><b> int j=0;</b></p><p> CChatRoomServerDlg
45、 *ServerDlg=(CChatRoomServerDlg *)AfxGetApp()->GetMainWnd();</p><p> //解析客服端發(fā)來(lái)的消息以便確定消息的類(lèi)型</p><p> switch(CmdFlag)</p><p><b> {</b></p><p> case CON
46、NECT: //用戶(hù)發(fā)來(lái)的連接請(qǐng)求</p><p> //對(duì)用戶(hù)發(fā)來(lái)的用戶(hù)名和密碼進(jìn)行判斷</p><p> strTemp = CString(RecvData.GetAt(1).GetBuffer(RecvData.GetAt(1).GetLength()));</p><p> ZeroMemory(sendBuff,1024);<
47、;/p><p> //將JOIN命令和用戶(hù)名填入緩沖區(qū) sprintf(sendBuff,"5|%s|",RecvData.GetAt(1).GetBuffer(RecvData.GetAt(1).GetLength()));for( i=0;i<count;i++) //向除自己以外的所有在線用戶(hù)發(fā)送一條加入消息</p><p>
48、;<b> {</b></p><p> //SOCKET tempsocket = ((UserInfo *)UserList.GetAt(j))->UserSocket;</p><p> if (RecvData.GetAt(1).GetBuffer(RecvData.GetAt(1).GetLength()) != User[i].UserName
49、)</p><p><b> {</b></p><p> if(SOCKET_ERROR == send(User[i].UserSocket,sendBuff,strlen(sendBuff),0))</p><p><b> {</b></p><p> AfxMessageBox(&
50、quot;connect 中向各用戶(hù)發(fā)送消息失??!");</p><p><b> break;</b></p><p><b> }</b></p><p><b> }</b></p><p><b> }</b><
51、/p><p> //向該用戶(hù)發(fā)送一條LIST消息使其將所有在線用戶(hù)加入用戶(hù)列表</p><p> ZeroMemory(sendBuff,1024);</p><p> strTemp="3|";</p><p> for(i=0;i<count;i++)</p><p><b>
52、; {</b></p><p> if (RecvData.GetAt(1).GetBuffer(RecvData.GetAt(1).GetLength()) != </p><p> User[i].UserName)</p><p><b> {</b></p><p> strTemp+=Us
53、er[i].UserName;</p><p> strTemp+="|";</p><p><b> }</b></p><p><b> }</b></p><p> sprintf(sendBuff,"%s",strTemp);</p>
54、;<p> if(count>0)</p><p><b> {</b></p><p> if(SOCKET_ERROR ==send(RecvSocket,sendBuff,strlen(sendBuff),0))</p><p><b> {</b></p><p>
55、; AfxMessageBox("connect中發(fā)送List數(shù)據(jù)失??!");</p><p><b> break ;</b></p><p><b> }</b></p><p><b> }</b></p><p> //將該用戶(hù)加入用戶(hù)列表
56、</p><p> for(i=0;i<count;i++)</p><p><b> {</b></p><p> if (RecvData.GetAt(1).GetBuffer(RecvData.GetAt(1).GetLength()) == User[i].UserName)</p><p><
57、b> {</b></p><p> comeFlag=FALSE;</p><p><b> }</b></p><p><b> }</b></p><p> if (comeFlag)</p><p><b> {</
58、b></p><p> User[count].UserName=</p><p> RecvData.GetAt(1).GetBuffer(RecvData.GetAt(1).GetLength());</p><p> User[count].UserSocket=RecvSocket;</p><p><b>
59、count++;</b></p><p><b> }</b></p><p> //將用戶(hù)登陸成功發(fā)送給用戶(hù)</p><p> ZeroMemory(sendBuff,1024);sprintf(sendBuff,"1|%s|",</p><p>
60、RecvData.GetAt(1).GetBuffer(RecvData.GetAt(1).GetLength()));</p><p> if( SOCKET_ERROR ==send(RecvSocket,sendBuff,strlen(sendBuff),0))</p><p><b> {</b></p><p> AfxMess
61、ageBox("CONNECT中向客戶(hù)端發(fā)送登陸成功消息失敗!");</p><p><b> break ;</b></p><p><b> }</b></p><p> //在服務(wù)器上加入用戶(hù)信息ServerDlg->AddToUserList(<
62、/p><p> RecvData.GetAt(1).GetBuffer(RecvData.GetAt(1).GetLength()));//將用戶(hù)加入用戶(hù)列表</p><p> strTemp=RecvData.GetAt(1).GetBuffer(RecvData.GetAt(1).GetLength());</p><p> iotime=CTime::Get
63、CurrentTime();</p><p> strTemp1=iotime.Format(" 于:%Y年%m月%d日 %H:%M:%S登錄");</p><p> strTemp+=strTemp1;</p><p> strTemp1="服務(wù)器";</p><p> ServerDlg-&
64、gt;SetChatRecord(strTemp1,strTemp);</p><p><b> break;</b></p><p> case CHAT: //群聊</p><p> ZeroMemory(sendBuff,1024);</p><p> //向所有其他在線的用戶(hù)轉(zhuǎn)發(fā)收到的
65、消息sprintf(sendBuff,"2|%s|%s|",</p><p> RecvData.GetAt(1).GetBuffer(RecvData.GetAt(1).GetLength()),</p><p> RecvData.GetAt(2).GetBuffer(RecvData.GetAt(2).GetLength()));&l
66、t;/p><p> for( i=0;i<count;i++)</p><p><b> {</b></p><p> if (RecvData.GetAt(1).GetBuffer(RecvData.GetAt(1).GetLength()) != User[i].UserName)</p><p><b
67、> {</b></p><p> send(User[i].UserSocket,sendBuff,strlen(sendBuff),0);</p><p><b> }</b></p><p><b> }</b></p><p> // 將收到的消息顯示
68、在服務(wù)器消息記錄框中ServerDlg->SetChatRecord(</p><p> RecvData.GetAt(1).GetBuffer(RecvData.GetAt(1).GetLength()), RecvData.GetAt(2).GetBuffer(RecvData.GetAt(2).GetLength()))
69、;</p><p><b> break;</b></p><p> case EXIT:</p><p> for(i=0;i<count;i++) //刪除用戶(hù)在UserList中的信息</p><p> {if(RecvData.GetAt(
70、1).GetBuffer(RecvData.GetAt(1).GetLength())==</p><p> User[i].UserName)</p><p><b> {</b></p><p> //UserList.RemoveAt(i);</p><p> for(j=i;j<count;j++)
71、</p><p><b> {</b></p><p> User[j].UserName=User[j+1].UserName;</p><p> User[j].UserSocket=User[j+1].UserSocket;</p><p><b> }</b></p&g
72、t;<p><b> }</b></p><p><b> }</b></p><p> //把退出的用戶(hù)從服務(wù)器用戶(hù)列表中刪除,同時(shí)向聊天記錄中更新一條退出的消息</p><p> strTemp=RecvData.GetAt(1).GetBuffer(RecvData.GetAt(1).
73、GetLength());</p><p> ServerDlg->DeleteFromUserList(strTemp);//將用戶(hù)從服務(wù)器“用戶(hù)列表”中刪除</p><p> iotime=CTime::GetCurrentTime();</p><p> strTemp1=iotime.Format(" 于:%Y年%m月%d日 %H:%M
74、:%S下線");</p><p> strTemp+=strTemp1;</p><p> strTemp1="服務(wù)器";</p><p> ServerDlg->SetChatRecord(strTemp1,strTemp);</p><p> //向其他用戶(hù)發(fā)送QUit消息</p>
75、<p> ZeroMemory(sendBuff,1024)</p><p> sprintf(sendBuff,"6|%s|",</p><p> RecvData.GetAt(1).GetBuffer(RecvData.GetAt(1).GetLength()));</p><p> for( i=0;i<count
76、;i++)</p><p><b> {</b></p><p> if (RecvData.GetAt(1).GetBuffer(RecvData.GetAt(1).GetLength()) !=</p><p> User[i].UserName)</p><p><b> {</b>&
77、lt;/p><p> send(User[i].UserSocket,sendBuff,strlen(sendBuff),0);</p><p><b> }</b></p><p><b> }</b></p><p> ContinueFlag=FALSE;</p>
78、<p><b> break;</b></p><p><b> default :</b></p><p> strTemp="無(wú)法識(shí)別的指令!";</p><p> strTemp1="服務(wù)器";</p><p> ServerD
79、lg->SetChatRecord(strTemp1,strTemp);</p><p><b> break;</b></p><p><b> }</b></p><p> RecvData.RemoveAll();</p><p> g_Mutex.Unlock();</p
80、><p> Sleep(10);</p><p><b> }</b></p><p> return TRUE;</p><p><b> }</b></p><p><b> 5.2客服端</b></p><p><
81、;b> (1).建立連接</b></p><p> UpdateData(TRUE);</p><p> if (m_username.IsEmpty()||m_pwd.IsEmpty())</p><p><b> {</b></p><p> MessageBox("用戶(hù)名或密
82、碼不能為空!");</p><p><b> return ;</b></p><p><b> }</b></p><p> g_ClientSocket=socket(AF_INET,SOCK_STREAM,0); //創(chuàng)建套接字</p><p> if( INVALID_S
83、OCKET == g_ClientSocket)</p><p><b> {</b></p><p> MessageBox("創(chuàng)建套接字失??!");</p><p> return ;</p><p><b> }</b></p><p>
84、 DWORD dwIP;</p><p> ((CIPAddressCtrl *)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dwIP);</p><p> SOCKADDR_IN clientaddr;</p><p> clientaddr.sin_family=AF_INET;</p><p
85、> clientaddr.sin_port=htons(m_port);</p><p> clientaddr.sin_addr.S_un.S_addr=htonl(dwIP);</p><p> if ( SOCKET_ERROR ==</p><p> connect(g_ClientSocket,(SOCKADDR *)&clienta
86、ddr,sizeof(SOCKADDR)))</p><p><b> {</b></p><p> MessageBox("連接服務(wù)器失??!");</p><p><b> return ;</b></p><p><b> }</b></p
87、><p> char sendBuff[1024]={0};</p><p> sprintf(sendBuff,"1|%s|%s|",m_username.GetBuffer(m_username.GetLength()),m_pwd.GetBuffer(m_pwd.GetLength()));</p><p> int sendlength
88、=strlen(sendBuff);</p><p> if ( SOCKET_ERROR == send(g_ClientSocket,sendBuff,sendlength,0)) //連接成功后將用戶(hù)名和密碼發(fā)給服務(wù)器</p><p><b> {</b></p><p> MessageBox("發(fā)送連接請(qǐng)求數(shù)據(jù)失?。?
89、quot;);</p><p><b> return ;</b></p><p><b> }</b></p><p> hRecvThread=CreateThread(NULL,0,RecvThread,NULL,0,NULL); //創(chuàng)建客戶(hù)端接收數(shù)據(jù)線程</p><p> Ge
90、tDlgItem(IDC_BTNSEND)->EnableWindow(TRUE);</p><p> GetDlgItem(IDC_USERLOAD)->EnableWindow(FALSE);</p><p> (2).接受數(shù)據(jù)線程</p><p> DWORD WINAPI RecvThread(LPVOID lpParameter)<
91、/p><p><b> {</b></p><p> while (TRUE)</p><p><b> {</b></p><p> g_Mutex.Lock();</p><p> BYTE recvBuff[RECV_DATA_SIZE + 2]={0};<
92、/p><p> int bufflength=sizeof(recvBuff);</p><p> int recvedSize = 0;</p><p> //Sleep(100);</p><p> recvedSize = recv(g_ClientSocket,(char*)recvBuff,bufflength,0);&
93、lt;/p><p> if ( SOCKET_ERROR == recvedSize)</p><p><b> {</b></p><p> AfxMessageBox("接收數(shù)據(jù)失?。?quot;);</p><p> break ;</p><p><b>
94、; }</b></p><p> CStringArray RecvData;</p><p> CChatRoomClientDlg::Split((char*)recvBuff,'|',RecvData); //此函數(shù)不會(huì)分解AUDIO命令,直接交個(gè)case處理</p><p> if (RecvData.GetSize()&
95、lt;=0) </p><p><b> {</b></p><p> continue ;</p><p><b> }</b></p><p> UINT CmdFlag=atoi(RecvData.GetAt(0).GetBuffer(RecvData.GetAt(0).GetLen
96、gth()));</p><p> int i=0; //循環(huán)時(shí)使用的增加量</p><p> CString strRecord="";</p><p> CString strTemp="";</p><p> CChatRoomClientDlg *ClientDlg=(CChatRoom
97、ClientDlg *)AfxGetApp()->GetMainWnd();</p><p> switch( CmdFlag)</p><p><b> {</b></p><p><b> case OK:</b></p><p> strTemp=RecvData.GetAt(1
98、).GetBuffer(RecvData.GetAt(1).GetLength());</p><p> strRecord="登陸成功";</p><p> ClientDlg->SetChatRecord(strTemp,strRecord);</p><p><b> break;</b></p
99、><p> case CHAT: //群聊</p><p> strTemp=RecvData.GetAt(1).GetBuffer(RecvData.GetAt(1).GetLength());</p><p> strRecord=RecvData.GetAt(2).GetBuffer(RecvData.GetAt(2).GetLength());</
100、p><p> ClientDlg->SetChatRecord(strTemp,strRecord);</p><p><b> break</b></p><p> case LIST: </p><p> for(i=1;i<RecvData.GetSize();i++)</p>
101、<p><b> {</b></p><p> strTemp=RecvData.GetAt(i).GetBuffer(RecvData.GetAt(i).GetLength());</p><p> ClientDlg->AddToUserList(strTemp);</p><p><b> }</
102、b></p><p><b> break;</b></p><p> case PRIVATE:</p><p> strTemp=RecvData.GetAt(1).GetBuffer(RecvData.GetAt(1).GetLength());</p><p> strTemp+="悄悄地
103、對(duì)你";</p><p> strRecord=RecvData.GetAt(2).GetBuffer(RecvData.GetAt(2).GetLength());</p><p> ClientDlg->SetChatRecord(strTemp,strRecord);</p><p><b> break;</b>&
104、lt;/p><p> case JOIN :</p><p> strTemp=RecvData.GetAt(1).GetBuffer(RecvData.GetAt(1).GetLength());</p><p> ClientDlg->AddToUserList(strTemp);</p><p><b> break
105、;</b></p><p> case QUIT:</p><p> strTemp=RecvData.GetAt(1).GetBuffer(RecvData.GetAt(1).GetLength());</p><p> ClientDlg->DeleteFromUserList(strTemp);</p><p>
106、<b> break;</b></p><p><b> default:</b></p><p> strTemp="服務(wù)器";</p><p> strRecord="無(wú)法識(shí)別的指令";</p><p> ClientDlg->SetCha
107、tRecord(strTemp,strRecord);</p><p> if (g_ClientSocket)</p><p><b> {</b></p><p> closesocket(g_ClientSocket);</p><p><b> }</b></p>
108、;<p> break;</p><p><b> }</b></p><p> RecvData.RemoveAll();</p><p> g_Mutex.Unlock();</p><p> Sleep(10);</p><p><b> }<
109、;/b></p><p> return TRUE;</p><p><b> }</b></p><p><b> (3).發(fā)送數(shù)據(jù)</b></p><p> char sendBuff[1024]={0};</p><p> CString sendMs
110、g="";</p><p> CString strTemp="";</p><p> GetDlgItemText(IDC_EDIT_MSG,sendMsg);</p><p> if (sendMsg.IsEmpty())</p><p><b> {</b></
111、p><p><b> return ;</b></p><p><b> }</b></p><p> //將發(fā)送的內(nèi)容發(fā)給服務(wù)器</p><p> sprintf(sendBuff,"2|%s|%s|",m_username,sendMsg.GetBuffer(sendMs
112、g.GetLength()));</p><p> if(SOCKET_ERROR==send(g_ClientSocket,sendBuff,strlen(sendBuff),0))</p><p><b> {</b></p><p> MessageBox("數(shù)據(jù)發(fā)送失?。?quot;);</p><p
113、><b> return ;</b></p><p><b> }</b></p><p> //將發(fā)送的內(nèi)容更新到自己的聊天記錄中</p><p> GetDlgItemText(IDC_EDITCHATMSG,strTemp);</p><p> strTemp+="\
114、r\n";</p><p> strTemp+=m_username;</p><p> strTemp+="說(shuō):";</p><p> strTemp+=sendMsg;</p><p> SetDlgItemText(IDC_EDITCHATMSG,strTemp);</p><p
115、> SetDlgItemText(IDC_EDIT_MSG,"");</p><p> 6 設(shè)計(jì)的總結(jié)和體會(huì)</p><p> 通過(guò)這學(xué)期對(duì)windows的學(xué)習(xí)以及以往對(duì)window程序設(shè)計(jì)的理解并在學(xué)校圖書(shū)館查閱相關(guān)資料,最終通過(guò)大家的努力完成了這個(gè)簡(jiǎn)單的局域網(wǎng)通信程序。雖然是個(gè)小程序,但通過(guò)這個(gè)程序的開(kāi)發(fā),讓我們對(duì)windows程序設(shè)計(jì)的一些相關(guān)的知識(shí)得
116、以鞏固,也提升我們對(duì)windows程序的認(rèn)識(shí)。</p><p> 在此次開(kāi)發(fā)過(guò)程中,我們使用了多線程的編程方式將數(shù)據(jù)監(jiān)聽(tīng)也數(shù)據(jù)的接受都做為一個(gè)線程來(lái)處理。并在接受數(shù)據(jù)線程里分解了發(fā)送來(lái)的數(shù)據(jù)并根據(jù)不同的命令來(lái)執(zhí)行不同的操作,這也是本程序的核心部分。通過(guò)這個(gè)程序我們理解了怎樣去建立一個(gè)TCP連接,以及如何使用TCP進(jìn)行數(shù)據(jù)的傳輸。</p><p><b> 7 參考文獻(xiàn)<
117、/b></p><p> [1] 任泰明著. TCP/IP協(xié)議與網(wǎng)絡(luò)編程. 西安電子科技大學(xué)出版社. 2004</p><p> [2] 鄧全良著. Winsock網(wǎng)絡(luò)程序設(shè)計(jì). 中國(guó)鐵道出版社. 2002</p><p> [3]《Visual C++6.0使用與開(kāi)發(fā)》 清華大學(xué)出版社,木林森、高峰霞、羅麗瓊、奚紅宇編著</p><
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫(kù)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- vc++課程設(shè)計(jì)--聊天室程序設(shè)計(jì)
- vc++設(shè)計(jì)簡(jiǎn)單的聊天室畢業(yè)設(shè)計(jì)
- 多線程與聊天室程序的創(chuàng)建
- vc++課程設(shè)計(jì)----用winsock實(shí)現(xiàn)聊天
- [vc++畢設(shè)]vc做的聊天室+論文
- java課程設(shè)計(jì)之簡(jiǎn)單聊天室
- vc++網(wǎng)絡(luò)聊天室的實(shí)現(xiàn)計(jì)算機(jī)操作系統(tǒng)課程設(shè)計(jì)
- 計(jì)算機(jī)網(wǎng)絡(luò)課程設(shè)計(jì)-- 用winsock實(shí)現(xiàn)聊天室的vc++程序設(shè)計(jì)
- 計(jì)算機(jī)網(wǎng)絡(luò)課程設(shè)計(jì)-- 用winsock實(shí)現(xiàn)聊天室的vc++程序設(shè)計(jì)
- vc++網(wǎng)絡(luò)聊天軟件課程設(shè)計(jì)
- 網(wǎng)絡(luò)編程課程設(shè)計(jì)-簡(jiǎn)單的聊天室程序設(shè)計(jì)
- 網(wǎng)絡(luò)編程課程設(shè)計(jì)-簡(jiǎn)單的聊天室程序設(shè)計(jì)
- web課程設(shè)計(jì)—— 聊天室
- java課程設(shè)計(jì)報(bào)告---利用java實(shí)現(xiàn)簡(jiǎn)單聊天室
- java課程設(shè)計(jì)--聊天室系統(tǒng)
- java網(wǎng)絡(luò)聊天室課程設(shè)計(jì)
- java課程設(shè)計(jì)---聊天室系統(tǒng)
- tcp課程設(shè)計(jì)--網(wǎng)絡(luò)聊天室
- 聊天室課程設(shè)計(jì)---聊天程序的設(shè)計(jì)和實(shí)現(xiàn)
- vc++課程設(shè)計(jì)---簡(jiǎn)單計(jì)算器的設(shè)計(jì)
評(píng)論
0/150
提交評(píng)論