

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、<p> TCP與UDP網絡通訊的應用開發(fā)</p><p> 摘 要:在網絡越來越發(fā)達的今天,人們對網絡的依賴越來越多,越來越離不開網絡,由此而產生的網絡通訊手段越來越多。本文主要以最常見的TCP和UDP通訊協(xié)議來實現(xiàn)網絡通訊,讓一臺計算機實現(xiàn)客戶機/服務機的功能。</p><p> 關鍵詞:網絡;通訊;TCP;UDP。</p><p><b&
2、gt; VC++語言綜述</b></p><p> 1.1C++的發(fā)展歷史</p><p> 當C語言發(fā)展到頂峰的時刻,出現(xiàn)了一個版本叫C with Class,那就是C++最早的版本,在C語言中增加class關鍵字和類,那個時候有很多版本的C都希望在C語言中增加類的概念;后來C標準委員會決定為這個版本的C起個新的名字,那個時候征集了很多種名字,最后采納了其中一個人的意見
3、,以C語言中的++運算符來體現(xiàn)它是C語言的進步,故而叫C++,成立了C++標準委員會。為了解決此類問題,Gosling決定開發(fā)一種新的語言,并取名為Oak。它采用了大部分與C++類似的語法對可能具備危險性的功能加以改進,例如將內存管理改為由語言自己進行管理,以減少程序員的負擔及可能發(fā)生的錯誤。Oak是一種可移置的語言,它是一種平臺獨立的語言,能夠在各種芯片上執(zhí)行,可以降低設備的研發(fā)成本。</p><p> 1.
4、2 C++的特點</p><p> C++這個詞在中國大陸的程序員圈子中通常被讀做“C加加”,而西方的程序員通常讀做“C plus plus”,“CPP”。 它是一種使用非常廣泛的計算機編程語言。C++是一種靜態(tài)數(shù)據(jù)類型檢查的,支持多重編程范式的通用程序設計語言。它支持過程化程序設計、數(shù)據(jù)抽象、面向對象程序設計、制作圖標等等泛型程序設計等多種程序設計風格。 </p><p> 1、C
5、++支持數(shù)據(jù)封裝,支持數(shù)據(jù)封裝就是支持數(shù)據(jù)抽象。</p><p> 2、C++類中包含私有、公有和保護成員C++類中可定義三種不同訪控制權限的成員。 </p><p> 3、C++語言中通過發(fā)關消息來處理對象C++中是通過向對象發(fā)關消息來處理對象的,每個對象根據(jù)所接收到的消息的性質來決定需要采取的行動,以響應這個消息。</p><p> 4、C++中允許友元破
6、壞封裝性類中的私有成員一般是不允許該類外面的任何函數(shù)訪問的,但是友元便可打破這條禁令。</p><p> 5、C++允許函數(shù)名和運算符重載C++支持多態(tài)性。</p><p> 6、C++支持繼承性C++中可以允許單繼承和多繼承。</p><p> 7、C++語言支持動態(tài)聯(lián)編C++中可以定義虛函數(shù),通過定義虛函數(shù)來支持動態(tài)聯(lián)編。</p><p
7、> TCP與UDP 網絡通訊 VC++編程的實現(xiàn)原理</p><p> 2.1.1關于UDP/IP協(xié)議</p><p> 這里我們針對UDP協(xié)議的結構進行一下詳述。對于UDP(UDP:User Datagram Protocol)來說,用戶數(shù)據(jù)報協(xié)議(UDP)是 ISO 參考模型中一種無連接的傳輸層協(xié)議,提供面向事務的簡單不可靠信息傳送服務。 UDP協(xié)議基本上是 IP 協(xié)議與
8、上層協(xié)議的接口。 UDP協(xié)議適用端口分辨運行在同一臺設備上的多個應用程序。</p><p> 由于大多數(shù)網絡應用程序都在同一臺機器上運行,計算機上必須能夠確保目的地機器上的軟件程序能從源地址機器處獲得數(shù)據(jù)包,以及源計算機能收到正確的回復。這是通過使用 UDP的“端口號”完成的。例如,如果一個工作站希望在工作站 128.1.123.1 上使用域名服務系統(tǒng),它就會給數(shù)據(jù)包一個目的地址 128.1.123.1 ,并在
9、 UDP頭插入目標端口號 53 。源端口號標識了請求域名服務的本地機的應用程序,同時需要將所有由目的站生成的響應包都指定到源主機的這個端口上。 UDP端口的詳細介紹可以參照相關文章。</p><p> 與 TCP不同, UDP協(xié)議并不提供對 IP 協(xié)議的可靠機制、流控制以及錯誤恢復功能等。由于 UDP比較簡單, UDP頭包含很少的字節(jié),比 TCP負載消耗少。</p><p> UDP適
10、用于不需要 TCP可靠機制的情形,比如,當高層協(xié)議或應用程序提供錯誤和流控制功能的時候。 UDP協(xié)議是傳輸層協(xié)議,服務于很多知名應用層協(xié)議,包括網絡文件系統(tǒng)(NFS)、簡單網絡管理協(xié)議(SNMP)、域名系統(tǒng)(DNS)以及簡單文件傳輸系統(tǒng)(TFTP)。</p><p><b> UDP協(xié)議結構</b></p><p> Source Port — 16位。源端口是可
11、選字段。當使用時,它表示發(fā)送程序的端口,同時它還被認為是沒有其它信息的情況下需要被尋址的答復端口。如果不使用,設置值為0。</p><p> Destination Port — 16位。目標端口在特殊因特網目標地址的情況下具有意義。</p><p> Length — 16位。該用戶數(shù)據(jù)報的八位長度,包括協(xié)議頭和數(shù)據(jù)。長度最小值為8。</p><p> Ch
12、ecksum — 16位。IP 協(xié)議頭、UDP協(xié)議頭和數(shù)據(jù)位,最后用0填補的信息假協(xié)議頭總和。如果必要的話,可以由兩個八位復合而成。</p><p> Data — 包含上層數(shù)據(jù)信息。</p><p> 2.1.2MFC集成開發(fā)環(huán)境</p><p> 在比較低級的編程方法中,如用Win32直接編寫WindowsAPI應用程序,代碼量是非常大的,因為你所要照顧
13、的細節(jié)太多了。例如,你用某種類型的結構來接收單擊鼠標事件。你的事件循環(huán)中的代碼會查看結構中不同域,以確定哪個用戶界面對象受到了影響,然后會完成相應的操作。當屏幕上有很多對象時,應用程序會變得很大。只是簡單地處?哪個對象被單擊和對它需要做些什么要花費大量的代碼。幸運的是,你可以在比較高級的方法來進行編程,這就是使用MFC。在MFC中,幾乎所有的低級的細節(jié)處理都為你代辦了。如果你把某一用戶界面對象放在屏幕上,你只需要兩行代碼來 建立它。如果
14、用戶單擊一個按鈕,則按鈕自己會完成一切必要的操作,從更新屏幕上的外觀到調用你程序中的預處理函數(shù)。該函數(shù)包含有對該按鈕作出相應操作的代碼。MFC 為你處理所有的細節(jié):你建立按鈕并告知它特定的處理函數(shù),則當它被按下時,它就會調用相應的函數(shù)。 </p><p> Visual C++ 不僅僅是一個編譯器。它是一個全面的應用程序開發(fā)環(huán)境,使用它你充分 利用具有面向對象特性的 C++ 來
15、開發(fā)出專業(yè)級的 Windows 應用程序。為了能充分利用這些 特性,你必須理解 C++ 程序設計語言。掌握了C++,你就必須掌握 Microsoft 基本類庫 (MFC) 的層次結構。該層次 結構包容了 Windows API 中的用戶界面部分,并使你能夠很容易地以 面向對象的方式建立 Windows 應用程序。這種層次結構適用于所有版本的 Windows 并彼此兼容。你用 MFC 所建立的代碼是完全可移植的。</p>&
16、lt;p> 2.1.3 多線程技術</p><p> 傳統(tǒng)操作系統(tǒng)中的單線程進程由進程控制塊和用戶地址空間、以及管理進程執(zhí)行的調用/返回行為的系統(tǒng)堆?;蛴脩舳褩嫵?。如果把進程的管理和執(zhí)行相分離,進程作為操作系統(tǒng)中進行保護和資沮分配的單位,允許一個進程中包含有多個可并發(fā)執(zhí)行的控制流,這些控制流切扒時不必通過進程調度,通信時可以直接借助于共享的內存區(qū),這就形成了多線積進程。</p><
17、;p> 目前,大多數(shù)操作系統(tǒng)都采用多線內核模型,支持多線程(結構)進程。因而,對于應用軟件的開發(fā)來說,出現(xiàn)了另外一種設計思路,即并發(fā)多線程程序設計的方法。合理的多線程軟件結構,可以使得系統(tǒng)性能獲得較大提高,具體表現(xiàn)在:</p><p> 1.改進程序結構。對許多程序來說,如果把程序分成多個獨立或半獨立的執(zhí)行單元,而不是把程序設計成一個單一的復雜流程,將使程序有更高效的結構。</p><
18、;p> 2.快速線程切換,改進程序的實時響應能力。多個服務器程序的任務能夠單獨以線程的方式執(zhí)行,而線程的切換可以在同一個進程內進行,不需要在應用程序中維護人為的切換界面。客戶程序也不用擔心它們的請求會由于其他客戶程序的請求所要時間太長而別拒絕。</p><p> 3.減少(系統(tǒng))管理開銷,(線程)通信易于實現(xiàn),節(jié)省內存空間。</p><p> 4.并行程度提高。在單個處理器上運
19、行一個多線程進程,系統(tǒng)將在多個線程之間切換處理器資源,即輪流為這些線程分配時間片,也就是并發(fā)執(zhí)行。</p><p> TCP與UDP的領域簡介</p><p> TCP發(fā)送的包有序號,對方收到包后要給一個反饋,如果超過一定時間還沒收到反饋就自動執(zhí)行超時重發(fā),因此TCP最大的優(yōu)點是可靠。一般網頁(http)、郵件(SMTP)、遠程連接(Telnet)、文件(FTP)傳送就用TCP<
20、/p><p> UDP是面向消息的協(xié)議,通信時不需要建立連接,數(shù)據(jù)的傳輸自然是不可靠的,一般用于多點通信和實時的數(shù)據(jù)業(yè)務,比如語音廣播、視頻、QQ、TFTP(簡單文件傳送)、SNMP(簡單網絡管理協(xié)議)、RTP(實時傳送協(xié)議)RIP(路由信息協(xié)議,如報告股票市場,航空信息)、DNS(域名解釋)。注重速度流暢。</p><p><b> 應用實例</b></p&g
21、t;<p> UDP實例--網絡對戰(zhàn)五子棋</p><p><b> UDP的主要流程圖</b></p><p><b> 應用實例簡介:</b></p><p><b> ?、殴δ苄枨?lt;/b></p><p> ?、倌芡ㄟ^網絡進行下棋</p>
22、<p> ②符合五子棋的基本規(guī)則</p><p> ?、厶峁罢J輸”、“和棋”、“悔棋”等功能</p><p> ?、芴峁╇p方的倒計時功能</p><p> ?、萏峁┧阶鴺撕痛怪弊鴺斯δ?lt;/p><p> ⑥能在棋子上顯示的落子的順序數(shù)</p><p><b> ?、咛峁┒喾N背景</b
23、></p><p> ?、嗵峁┩婕抑g的聊天功能</p><p><b> ?、嵊斜尘耙魳?lt;/b></p><p> ⑩可自行輸入用戶名稱</p><p><b> ?、骗h(huán)境需求</b></p><p> ?、?0/10Mbps共享式HUB一臺</p>
24、<p> ?、谘b有Windows95/98/NT/XP操作系統(tǒng)的計算機兩臺</p><p> ③計算機的CPU不低于PII450,內存不小于64M</p><p> ?、?0/10Mbps自適應網卡每臺計算機各一塊,SB兼容聲卡各一塊,5類雙絞線若干米</p><p> ?、菝颗_計算機都應配置有TCP/IP協(xié)議</p><p>&
25、lt;b> ?、怯脩艚缑嫘枨?lt;/b></p><p><b> ?、俳缑嬗押?、親切</b></p><p><b> ②界面簡潔、不花哨</b></p><p> ?、鄄僮鹘缑嬷庇^、不繁瑣</p><p><b> ?、犬惓L幚硇枨?lt;/b></p>
26、;<p> ?、佼敹丝谔枦_突時,錯誤提示并可重新輸入</p><p> ?、诋敵霈F(xiàn)錯誤行列時,此次操作無效</p><p> ?、廴绻W絡非正常斷開,則終止此局</p><p> 用戶可自行輸入本文信息作為自己的用戶名稱,并顯示在窗體Form1的Label1或Label3上(主機為Label1,客戶機為Label3)。如果用戶不輸入任何字符,則程序將
27、以默認的“玩家一”或“玩家二”作為用戶名稱(主機默認為“玩家一”,客戶機默認為“玩家二”)。命令如下:</p><p> If Text1.Text <> "" Then Form1.Label1.Caption = Form2.Text1.Text</p><p> 或 If Text1.Text <> "" Then
28、Form1.Label3.Caption = Form2.Text1.Text</p><p> 當雙方連接成功以后,作為客戶機一方將主動把自己的用戶名稱發(fā)送給主機。主機收到后將其顯示在Label3上,然后再將自己的用戶名稱發(fā)送給客戶機??蛻魴C收到后將其顯示在Label1上。自此,雙方的用戶名稱傳送結束,并顯示在了各自的位置上。</p><p><b> ?、嬗螒蛟O置</
29、b></p><p> 游戲中雙方用戶的電腦,一臺作為主機,另一臺則作為客戶機。</p><p> ⑴如果選擇“我要當主機”,則用戶電腦將作為主機使用。</p><p> 在Text2文本框中將自動顯示出主機的IP地址。這里是利用Form2.Text2.Text = Form1.Winsock1.LocalIP語句來獲取主機的IP地址的。但是,在某些情況
30、下,Winsock1.LocalIP所獲取的IP地址并不全面,例如:用戶如果通過ADSL上網,Winsock1.LocalIP所獲取的IP地址并不是電腦在Internet上的IP地址,而是在局域網中的IP地址。</p><p> 本軟件默認的連接端口號為7626。當執(zhí)行Form1.Winsock1.Listen監(jiān)聽語句后,主機監(jiān)聽本地的7626端口。但是,如果7626端口已經被其他的應用程序所使用,那么,當程序
31、執(zhí)行到監(jiān)聽語句時將出現(xiàn)錯誤,并被系統(tǒng)所終止執(zhí)行。</p><p> 為避免這種情況,必須在相關的Sub過程中增加相應的錯誤處理語句,命令如下:</p><p> On Error GoTo CheckError</p><p> 當錯誤發(fā)生時,通知程序在分支點(執(zhí)行錯誤處理的地方)設置或激活錯誤捕獲。然后,On Error 語句激活捕獲并指引應用程序到標記著錯
32、誤處理開始的標號處,本程序為CheckError。</p><p> CheckError:</p><p> MsgBox Str(Err.Number) + vbCrLf + Err.Description, 0, "出錯"</p><p> 彈出對話框,顯示錯誤號和錯誤描述</p><p> 自此,錯誤被成功
33、捕獲。程序將不會被系統(tǒng)終止執(zhí)行。用戶可以重新輸入一個新的端口號,以避免發(fā)生沖突。</p><p> ?、迫绻x擇“我要加入一個棋局”,則用戶的電腦將作為客戶機使用。</p><p> Text2文本框中的IP地址為將要連接的遠程主機的IP地址或主機名。Text3文本框中的端口號為將要連接的遠程主機的端口號。</p><p> 對于客戶機來說,無須指定發(fā)送數(shù)據(jù)的本
34、地端口。Form1.Winsock1.LocalPort = 0語句將隨機選擇一個端口。在建立起連接以后,它就是用于TCP連接的本地端口。</p><p><b> 規(guī)則</b></p><p><b> ㈠下棋規(guī)則:</b></p><p> 黑方先行,雙方輪流依次落子。在一方落子之前,另一方必須等待。</p
35、><p> 為實現(xiàn)這個功能,必須使雙方的棋盤交替處于激活(True)狀態(tài)。</p><p> 在雙方網絡未連接成功以前,雙方的棋盤均處于禁止(False)狀態(tài),不接受落子操作。一旦,網絡連接成功,持黑子的一方率先使用Form1.Picture1.Enabled = True語句來激活本方棋盤。此時,黑方棋盤可以接受落子操作。用戶用鼠標在棋盤的相應位置上點擊左鍵,程序捕獲鼠標在棋盤上的點擊位
36、置,并計算出所處行列,在相應位置上顯示一枚黑色棋子。自此,黑方操作結束,棋盤再次被Picture1.Enabled = False語句所禁止。然后,將落子的行列信息傳送給白方。</p><p> 白方接收到黑方的落子信息后,先在本方棋盤的相應位置上顯示一枚黑色棋子。然后,使用Form1.Picture1.Enabled = True語句來激活本方棋盤進行落子操作。落子后,禁止本方棋盤,再發(fā)送棋子信息給黑方。&l
37、t;/p><p> 雙方重復上述操作直到此局結束為止。</p><p><b> ?、鎰儇撘?guī)則:</b></p><p> ⑴率先在棋盤上形成橫向、豎向或斜向上連續(xù)的相同顏色的五個棋子(含五個以上)的一方為勝。在15*15的棋盤上,共有八種獲勝可能。如圖4.5所示: </p><p><b> 圖4.5<
38、;/b></p><p> 其中,1、5為反斜向五子連珠,3、7為正斜向五子連珠,2、6為豎向五子連珠,4、8為橫向五子連珠。</p><p> 根據(jù)每一種不同方向上的獲勝情況,它們的判別程序也有所不同:</p><p><b> 反斜向五子連珠:</b></p><p><b> 正斜向五子連珠
39、:</b></p><p><b> 豎向五子連珠:</b></p><p><b> 橫向五子連珠:</b></p><p> ?、埔环秸J輸,則另一方獲勝</p><p> 在游戲運行過程中,如果一方點擊Form1.Command5按鈕,則被判負,并向對方發(fā)送“認輸”信息。為了避
40、免用戶在游戲過程中誤點Command5按鈕,在此設計了一個確認對話框,以確認用戶是否“認輸”。確認操作必須在10秒內完成,否則被將視為否認操作。</p><p><b> ㈢和棋規(guī)則: </b></p><p><b> ?、牌灞P滿</b></p><p> 當棋盤上的225個交叉位置上均有棋子,但雙方均未五子連珠,則
41、判為雙方和棋。在此設計了一個計數(shù)器C,每下一步棋或則接收到一步棋時,計數(shù)器均C均加1。當計數(shù)器達到225時,則表示棋盤已滿,雙方和棋。</p><p><b> ?、齐p方協(xié)商:</b></p><p> 在游戲運行過程中,如果一方點擊Form1.Command6按鈕,則向對方對方提出“和棋”請求。對方在收到和棋請求后,彈出確認對話框,對方可以點擊“是”來接受“和棋”
42、請求,也可以點擊“否”來拒絕“和棋”請求。一旦對方接受“和棋”請求,則本局結束,雙方和棋。</p><p> 為避免用戶在游戲過程中誤點Command6按鈕,在這也同樣設計了一個確認對話框。</p><p> 另外,為防止用戶在游戲過程中無限制的連續(xù)的點擊此按鈕,破壞游戲的可玩性。在此還設計了一個防止連續(xù)點擊的程序。一旦,用戶確認自己的“和棋”的操作,Command6按鈕就被禁止,用戶
43、無法再次點擊。只有等到下一次該用戶下棋為止,Command6按鈕才被再次激活。</p><p><b> ㈢執(zhí)黑規(guī)則:</b></p><p> 對弈雙方連接成功以后,由選擇“我要當主機”的主機方率先執(zhí)黑,以后各盤雙方輪流執(zhí)黑。</p><p><b> 代碼摘要 </b></p><p
44、><b> 服務器端</b></p><p><b> 服務器發(fā)送消息:</b></p><p> void CServer::SendMsg(CClientSocket *pClientSocket, CString Msg)</p><p><b> {</b></p>
45、<p> if(pClientSocket!=NULL)</p><p> pClientSocket->Send(Msg,Msg.GetLength());</p><p><b> }</b></p><p><b> 啟動服務器:</b></p><p> void
46、 CServer::StartServer()</p><p><b> {</b></p><p> if(m_Port==0)</p><p><b> {</b></p><p> MessageBox(_T("請輸入服務器端口"));</p><
47、;p><b> return;</b></p><p><b> }</b></p><p> if(m_pListenSocket!=NULL)</p><p><b> {</b></p><p> MessageBox(_T("服務器已經開啟&q
48、uot;));</p><p><b> return;</b></p><p><b> }</b></p><p> m_pListenSocket=new CListenSocket(this);</p><p> if(m_pListenSocket->Create(m_Por
49、t))</p><p><b> {</b></p><p> if(!m_pListenSocket->Listen())</p><p> MessageBox(_T("服務器開啟失敗"));</p><p><b> else</b></p>&
50、lt;p><b> {</b></p><p> if(LoadPlayer())</p><p> MessageBox(_T("服務器開啟成功"));</p><p><b> else</b></p><p> MessageBox(_T("服務器
51、數(shù)據(jù)出錯"));</p><p><b> }</b></p><p><b> }</b></p><p><b> }</b></p><p><b> 關閉服務器:</b></p><p> void CS
52、erver::ShutDownServer()</p><p><b> {</b></p><p> if(m_pListenSocket!=NULL)</p><p><b> {</b></p><p> CString Msg=_T("_SHUTDOWN_ ")
53、;</p><p> POSITION p=m_LogInList.GetHeadPosition();</p><p> int n=m_LogInList.GetCount();</p><p> CClientSocket* TempClient;</p><p> for(int i=0;i<n;i++)</p&g
54、t;<p><b> {</b></p><p> TempClient=(CClientSocket*)m_LogInList.GetNext(p);</p><p> SendMsg(TempClient,Msg);</p><p> delete TempClient;</p><p><
55、;b> }</b></p><p> delete m_pListenSocket;</p><p> m_pListenSocket=NULL;</p><p> m_NumOfClient=0;</p><p> m_NumOfGame=0;</p><p> m_pDlg->m
56、_ClientNum=0;</p><p> m_pDlg->m_PlayerList.ResetContent();</p><p> m_pDlg->m_GameNum=0;</p><p> m_pDlg->m_GameList.ResetContent();</p><p> SavePlayer();<
57、;/p><p> m_ConnectionList.RemoveAll();</p><p> m_LogInList.RemoveAll();</p><p> m_PlayerList.RemoveAll();</p><p> m_GameList.RemoveAll();</p><p> m_Top10
58、List.RemoveAll();</p><p> MessageBox(_T("服務器關閉成功"));</p><p> m_pDlg->UpdateData(FALSE);</p><p><b> }</b></p><p><b> }</b></p
59、><p><b> 客戶端</b></p><p><b> 客戶端發(fā)送消息:</b></p><p> void CClient::SendMsg(CString Msg)</p><p><b> {</b></p><p> if(m_pSo
60、cket!=NULL)</p><p> m_pSocket->Send(Msg,Msg.GetLength());</p><p><b> }</b></p><p><b> 客戶端登錄:</b></p><p> void CClient::LogInMsg(PTSTR pMs
61、g)</p><p><b> {</b></p><p> m_Player.SetScore((UINT)atoi(pMsg+12));</p><p> m_pLogInDlg->EndDialog(IDOK);</p><p><b> }</b></p><
62、;p><b> 創(chuàng)建會話:</b></p><p> void CClient::CreateMsg(PTSTR pMsg)</p><p><b> {</b></p><p> m_InGame=TRUE;</p><p> m_pView->m_GameNameText=
63、pMsg+12;</p><p> m_pWeiQi->m_Color=BLACK;</p><p> m_pView->UpdateData(FALSE);</p><p><b> }</b></p><p><b> 客戶端加入游戲:</b></p><
64、p> void CClient::JoinGameMsg(PTSTR pMsg)</p><p><b> {</b></p><p> int i=12,j,k;</p><p> while(pMsg[i]!=_T(' ')) i++;</p><p> pMsg[i]=0;</
65、p><p><b> j=i+1;</b></p><p> while(pMsg[j]!=_T(' ')) j++;</p><p> pMsg[j]=0;</p><p><b> k=j+1;</b></p><p> while(pMsg[k]!
66、=_T(' ')) k++;</p><p> pMsg[k]=0;</p><p> m_GameName=pMsg+12;</p><p> m_InGame=TRUE;</p><p> m_GameStart=TRUE;</p><p> m_pView->m_GameNameT
67、ext=m_GameName;</p><p> m_pView->m_Player2Info=pMsg+i+1;</p><p> m_pView->m_Player2Info+=_T("\r\n等級:");</p><p> m_pView->m_Player2Info+=pMsg+j+1;</p>&l
68、t;p> m_pView->m_Player2Info+="\r\n積分:";</p><p> m_pView->m_Player2Info+=pMsg+k+1;</p><p> m_pWeiQi->m_Color=WHITE;</p><p> m_pView->m_Color=BLACK;</p
69、><p> m_pView->UpdateData(FALSE);</p><p><b> }</b></p><p> void CClient::OneJoinMsg(PTSTR pMsg)</p><p><b> {</b></p><p> Messa
70、geBox(_T("有人加入你的游戲"));</p><p> int i=12,j;</p><p> while(pMsg[i]!=_T(' ')) i++;</p><p> pMsg[i]=0;</p><p><b> j=i+1;</b></p>&l
71、t;p> while(pMsg[j]!=_T(' ')) j++;</p><p> pMsg[j]=0;</p><p> m_InGame=TRUE;</p><p> m_GameStart=TRUE;</p><p> m_pView->m_Player2Info=pMsg+12;</p&g
72、t;<p> m_pView->m_Player2Info+="\r\n等級:";</p><p> m_pView->m_Player2Info+=pMsg+i+1;</p><p> m_pView->m_Player2Info+="\r\n積分:";</p><p> m_pVie
73、w->m_Player2Info+=pMsg+j+1;</p><p> m_pWeiQi->m_Color=BLACK;</p><p> m_pView->m_Color=BLACK;</p><p> m_pView->UpdateData(FALSE);</p><p><b> }</
74、b></p><p><b> 若主機不存在:</b></p><p> void CClient::HostExitMsg(PTSTR pMsg)</p><p><b> {</b></p><p> m_InGame=FALSE;</p><p> m_
75、GameStart=FALSE;</p><p> MessageBox(_T("主機已退出"));</p><p> m_pView->m_GameNameText=_T("");</p><p> m_pView->m_Player2Info=_T("");</p>&l
76、t;p> m_pView->UpdateData(FALSE);</p><p><b> }</b></p><p><b> 客戶端退出:</b></p><p> void CClient::ClientExitMsg(PTSTR pMsg)</p><p><b&g
77、t; {</b></p><p> m_GameStart=FALSE;</p><p> MessageBox(_T("對方已退出"));</p><p> m_pView->m_Player2Info=_T("");</p><p> m_pView->Update
78、Data(FALSE);</p><p><b> }</b></p><p><b> 心得體會:</b></p><p> 在做實驗之前首先要了解端對端聊天的詳細流程以及工作原理,然后選取適當?shù)目丶约翱丶膶傩詫ζ溥M行編碼,盡可能的實現(xiàn)所需要的功能。</p><p> 1首先要設置服務
79、端,并檢測服務端所開放的端口,并對網絡進行監(jiān)聽(ServerSocket)。</p><p> 2打開客戶端再選擇設置自身開放的端口號和服務端開放的端口號,并向服務端發(fā)出連接請求。</p><p> 3服務端監(jiān)聽到客戶端的連接請求,并同意連接,連接成功后即可發(fā)送信息進行聊天。</p><p> TCP實例--網絡聊天室</p><p>
80、<b> TCP的主要流程圖</b></p><p><b> 應用實例簡介</b></p><p> 局域網聊天系統(tǒng)使該系統(tǒng)的用戶能夠通過客戶端登入到該系統(tǒng),然后直接與系統(tǒng)交互。首先,需啟動服務器,進行服務器的配置,進行正確的服務器配置和數(shù)據(jù)庫連接并測試成功后,開啟服務器。接下來,在客戶端,該系統(tǒng)的用戶能夠通過登陸界面進入,然后直接與系統(tǒng)
81、交互,進行文字傳送。本系統(tǒng)支持的活動列表如下:</p><p> 配置服務器,設置IP及端;</p><p><b> 開啟服務器;</b></p><p> 對離線用戶進行刪除管理;</p><p><b> 用戶登陸系統(tǒng);</b></p><p> 用戶與系統(tǒng)交
82、互,進行文字傳送;</p><p> 用戶好友登陸后,自動刷新列表;</p><p> 傳送文字,當好友不在線時,發(fā)送離線消息;</p><p><b> 上線接收離線消息;</b></p><p> 該聊天程序分為服務器端和課戶端兩個部分。</p><p><b> 客戶端實
83、現(xiàn)功能:</b></p><p> 向在線成員發(fā)送消息并接收消息。</p><p> 更新成員狀態(tài)。當其他成員上線或下線時,客戶端及時更新成員狀態(tài)。</p><p> 更新成員列表,當其他成員加入或者偶成員被刪除時,客戶端及時更新成員列表。</p><p> 當對方不在線時,可以向該成員發(fā)送離線消息。</p>
84、<p> 當用戶上線時,接受其他用戶的離線消息。</p><p><b> 保存聊天記錄。</b></p><p><b> 服務器端實現(xiàn)功能:</b></p><p> 維護聊天室成員列表:包括接受新成員,刪除已有成員。</p><p> 通知客戶端更新成員狀態(tài)。</p
85、><p> 通知客戶端更新成員列表。</p><p> 為離線用戶保存離線消息。</p><p><b> 驗證密碼。</b></p><p> 禁止已登陸用戶再次登陸。</p><p><b> 保存用戶信息。</b></p><p> 為用
86、戶保存離線消息。</p><p><b> 關系圖如圖所示:</b></p><p><b> 關系功能圖</b></p><p><b> 系統(tǒng)設計</b></p><p><b> 設計原則</b></p><p>
87、考慮到系統(tǒng)的可重用性和伸縮性,需要將本系統(tǒng)的網絡通信底層和應用系統(tǒng)分離開。這樣,基于可重用的網絡通信層,可以實現(xiàn)其他各種實時性較高的應用系統(tǒng)。</p><p> 本系統(tǒng)在架構設計上將分4個層次,如圖3.2所示。</p><p><b> 圖3.2架構層次</b></p><p> 本系統(tǒng)最底層是Socket通信層,將負責客戶端和服務器之間
88、快速的數(shù)據(jù)交換,它通過接口層和最上面應用層保持實時數(shù)據(jù)聯(lián)系。用戶從客戶端進入到本系統(tǒng)前,將實現(xiàn)統(tǒng)一的用戶登錄驗證機制。Socket底層設計分兩大部分:協(xié)議設計和連接處理設計:協(xié)議設計和連接處理設計;CSocket層的目的是提供底層和應用蹭一個中介媒體的作用,但是不能設計得太復雜,以免延誤數(shù)據(jù)傳送時間。</p><p><b> 代碼摘要</b></p><p>&l
89、t;b> 服務器端</b></p><p><b> 主函數(shù):</b></p><p> void main()</p><p><b> {</b></p><p> //T:1、初始化:初始化Winsock32庫-------------------------<
90、;/p><p> //定義WINSOCK32結構體</p><p> WSADATA wsaData;</p><p> //MAKEWORD宏(socket庫主版本,次版本)</p><p> WORD wVersionRequested = MAKEWORD( 1, 1 );</p><p> //初始化Wi
91、nsock32庫WSAStartup(版本WORD,[out]WINSOCK32結構體) 計數(shù)++</p><p> int err = WSAStartup( wVersionRequested, &wsaData );</p><p> if ( err != 0 ) </p><p><b> {</b></p&g
92、t;<p><b> return;</b></p><p><b> }</b></p><p> //請求的socket庫版本 失敗。1 || 1 對應 MAKEWORD( 1, 1 )</p><p> if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYT
93、E( wsaData.wVersion ) != 1 ) </p><p><b> {</b></p><p> WSACleanup( );</p><p><b> return; </b></p><p><b> }</b></p><p&
94、gt; //T:2、建立:建立socket對象</p><p> //建立socket對象socket(AF_INET,SOCK_STREAM數(shù)據(jù)流或SOCK_DGRAM數(shù)據(jù)報,IPPROTO_IP);</p><p> SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);</p><p> //T:
95、3、綁定:設定本機 綁定監(jiān)聽 的 地址、端口</p><p> //為socket分配要監(jiān)聽的:地址、端口</p><p> sockaddr_in addrSrv;</p><p> addrSrv.sin_family=AF_INET;</p><p> addrSrv.sin_addr.S_un.S_addr=htonl(INA
96、DDR_ANY);//監(jiān)聽端口:INADDR_ANY或指定inet_addr("127.0.0.1")</p><p> addrSrv.sin_port=htons(6000);//監(jiān)聽端口</p><p> //綁定本機 sockaddr_in</p><p> err=bind(sockSrv,(SOCKADDR*)&addr
97、Srv,sizeof(sockaddr_in));</p><p> if(err==SOCKET_ERROR)</p><p><b> {</b></p><p> int nSockErr = WSAGetLastError();</p><p> printf("綁定錯誤:%d!\n"
98、, nSockErr);</p><p><b> return;</b></p><p><b> }</b></p><p> //T:4、監(jiān)聽:監(jiān)聽客戶連接請求</p><p> //監(jiān)聽listen(sockSrv,請求連接的隊列中允許的Max數(shù)目)</p><p
99、> err=listen(sockSrv,5);</p><p> if(err==SOCKET_ERROR)</p><p><b> {</b></p><p> int nSockErr =WSAGetLastError();</p><p> printf("監(jiān)聽錯誤:%d\n"
100、;, nSockErr);</p><p><b> return;</b></p><p><b> }</b></p><p><b> //提示狀態(tài)</b></p><p> printf("服務器啟動成功!\n");</p>&
101、lt;p> printf("服務器正在監(jiān)聽\n");</p><p> sockaddr_in addrClient;</p><p> int len=sizeof(SOCKADDR);</p><p> //T:5、接受連接:</p><p> //T:5.1、接受連接:若有客戶連接,則接受連接 acc
102、ept(sockSrv,[out]客戶信息指針,&len);</p><p> SOCKET sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len);</p><p> if(sockConn == INVALID_SOCKET)</p><p><b> {</b>
103、;</p><p> int nSockErr = WSAGetLastError();</p><p> printf("接受錯誤:%d\n",nSockErr);</p><p><b> //break;</b></p><p><b> }</b></p&g
104、t;<p><b> //獲得IP、端口</b></p><p> char* pIP=inet_ntoa(addrClient.sin_addr);</p><p> u_short pPort=ntohs(addrClient.sin_port);</p><p> char ss[100];</p>&
105、lt;p> sprintf(ss,"IP=%s PORT=%d",pIP,pPort);</p><p> printf("%s\n",ss);</p><p> //T:6.1、接收數(shù)據(jù)</p><p> char recvBuf2[100];</p><p> recv(sockC
106、onn,recvBuf2,100,0);</p><p> printf("%s\n",recvBuf2);</p><p> //T:6。2、發(fā)送:數(shù)據(jù)</p><p> char sendBuf[100];</p><p> sprintf(sendBuf,"%s","hello&
107、quot;);</p><p> send(sockConn,sendBuf,strlen(sendBuf)+1,0);</p><p> //T:7、關閉連接</p><p> closesocket(sockConn);</p><p> //T:8、清除套接字庫引用。 計數(shù)--</p><p> WSA
108、Cleanup();</p><p><b> }</b></p><p><b> 客戶端</b></p><p> void main()</p><p><b> {</b></p><p> //T:1、初始化:初始化Winsock32
109、庫-------------------------</p><p> //定義WINSOCK32結構體</p><p> WSADATA wsaData;</p><p> //MAKEWORD宏(socket庫主版本,次版本)</p><p> WORD wVersionRequested = MAKEWORD( 1, 1 );&
110、lt;/p><p> //初始化Winsock32庫WSAStartup(版本WORD,[out]WINSOCK32結構體) 計數(shù)++</p><p> int err = WSAStartup( wVersionRequested, &wsaData );</p><p> if ( err != 0 ) </p><p>&
111、lt;b> {</b></p><p><b> return;</b></p><p><b> }</b></p><p> //請求的socket庫版本 失敗。1 || 1 對應 MAKEWORD( 1, 1 )</p><p> if ( LOBYTE( wsa
112、Data.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) </p><p><b> {</b></p><p> WSACleanup( );</p><p><b> return; </b></p><p><b>
113、}</b></p><p> //T:2、建立:建立socket對象</p><p> //建立socket對象socket(AF_INET,SOCK_STREAM數(shù)據(jù)流或SOCK_DGRAM數(shù)據(jù)報,IPPROTO_IP);</p><p> SOCKET sockClient=socket(AF_INET,SOCK_STREAM,IPPROTO
114、_IP);</p><p> //T:3、連接:設定本機 要連接的server 地址、端口</p><p> //為socket分配要要連接:地址、端口</p><p> sockaddr_in addrSrv;</p><p> addrSrv.sin_family=AF_INET;</p><p> ad
115、drSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//監(jiān)聽端口:INADDR_ANY或指定inet_addr("127.0.0.1")</p><p> addrSrv.sin_port=htons(6000);//監(jiān)聽端口</p><p> //連接 addrSrv</p>&l
116、t;p> err=connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));</p><p> if(err==SOCKET_ERROR)</p><p><b> {</b></p><p> int nSockErr = WSAGetLastError();&l
117、t;/p><p> printf("連接錯誤:%d!\n", nSockErr);</p><p><b> return;</b></p><p><b> }</b></p><p><b> //T:4、發(fā)送:</b></p><
118、;p> char recvBuf[100];</p><p> send(sockClient,"我上線了",strlen("我上線了")+1,0);</p><p><b> //T:4、接收:</b></p><p> recv(sockClient,recvBuf,100,0);<
119、;/p><p> printf("%s\n",recvBuf);</p><p> //T:5、關閉連接</p><p> closesocket(sockClient);</p><p> //T:6、清除套接字庫引用。 計數(shù)--</p><p> WSACleanup();</p&g
120、t;<p><b> }</b></p><p><b> 總 結</b></p><p> 實現(xiàn)局域網即時通信,讓一臺計算機實現(xiàn)客戶機/服務機的功能,深入了解UDP協(xié)議和TCP協(xié)議的聯(lián)系與區(qū)別,根據(jù)對傳輸質量和效率的要求等各種考慮因數(shù),選擇是采用TCP,還是采用UDP;采用多線程技術,保證應用正常的工作,而不至于出現(xiàn)“假死
121、”現(xiàn)象。</p><p><b> 參考文獻:</b></p><p> [1] Stanley B.Lippman等. C++Primer(英文版). 人民郵電出版社2006-11 </p><p> [2] 陳堅,陳偉. Visual C++ 網絡高級編程. 人民郵電出版社 2001-08</p><p>
122、[3] JoeyGeorge[等]著. 世界著名計算機教材精選?面向對象系統(tǒng)分析與設計(第2版) 清華大學出版社 2008-01 </p><p> [4] 孫鑫、 余安萍等. VC++深入詳解 電子工業(yè)出版社 2006-06</p><p> [5] Kruglinski.D.J.,潘愛民, 王國印. VisualC++技術內幕(第4版)(修訂版) 清華大學出版社2009-04 &l
123、t;/p><p> [6] 王艷平,張越. WINDOWS網絡與通信程序設計(第二版).人民郵電出版社 2009-01</p><p> [7] Jeffrey Richter,Christophe Nasarre,葛子昂,周靖. Windows核心編程(第5版) 清華大學出版社. 2008-09</p><p> [8] 帕羅賽斯. MFC Windows程序設
124、計(第2版)(修訂版) 清華大學出版社 2007-05 </p><p> [9] 侯俊杰. 深入淺出MFC 華中科技大學出版社 2001-01</p><p> [10] 英特爾亞太研發(fā)有限公司、 英特爾軟件學院教材編寫組. 多核多線程技術. 上海交通大學出版社 2011-01 </p><p> [11] Jim Beveridge , Robert W
125、iener、 侯捷. Win32多線程序設計. 華中科技大學出</p><p> 版社 2002-01 </p><p> TCP and UDP network communication application development</p><p> design research</p><p> Abstract: In
126、the network more and more developed, the reliance on the network more and more, and become increasingly dependent on the network, the resulting network more and more means of communication. In this paper, the most common
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 畢業(yè)設計(論文)-基于modbus協(xié)議的聯(lián)控系統(tǒng)網絡通訊開發(fā)
- 網絡通訊技術的家庭應用
- 基于java的網絡通訊系統(tǒng)設計與實現(xiàn)(論文+系統(tǒng))
- 淺談光纖傳輸在網絡通訊中的應用
- 創(chuàng)造網絡通訊新時代
- 基于QT的UDP網絡廣播程序畢業(yè)論文.doc
- [學習]網絡通訊工具-即時通訊
- 畢業(yè)論文——淺析計算機網絡通訊存在的問題及其改進策略new
- 畢業(yè)設計---基于cs即時網絡通訊軟件的設計與實現(xiàn)
- 【zs精品】【畢業(yè)論文】丁滋汛(千里馬公司網絡通訊系統(tǒng))(全套)
- abplc及網絡通訊培訓教程
- abplc及網絡通訊培訓教程
- gsm通訊網絡干擾與優(yōu)化畢業(yè)論文
- gsm通訊網絡干擾與優(yōu)化畢業(yè)論文
- 基于JAVA的網絡通訊系統(tǒng)設計與實現(xiàn).doc
- FPSO多級自動監(jiān)控與網絡通訊研究.pdf
- 最新 網絡通訊協(xié)議圖 2016版
- 基于WinCC的控制網絡通訊設計.pdf
- 基于VoIP網絡通訊計費系統(tǒng)的設計與實現(xiàn).pdf
- 網絡通訊數(shù)據(jù)包截獲與解析研究.pdf
評論
0/150
提交評論