UDP的服務(wù)器設(shè)計(jì)說明書_第1頁
UDP的服務(wù)器設(shè)計(jì)說明書_第2頁
UDP的服務(wù)器設(shè)計(jì)說明書_第3頁
已閱讀5頁,還剩16頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、UDF的服務(wù)器設(shè)計(jì)說明書一 課程設(shè)計(jì)的目的和意義目的:設(shè)計(jì)一個基于UDP勺服務(wù)器意義:UDP是 TCP/IP協(xié)議族為傳輸層設(shè)計(jì)的兩個協(xié)議之一,它在進(jìn)程與進(jìn)程 的通信過程中,提供了有限的差錯校驗(yàn)功能,是一種無連接的,不可靠的協(xié) 議。UDP在一個較低的水平上完成進(jìn)程之間的通信,在收到分組的時候沒有流 量控制機(jī)制也沒有確認(rèn)機(jī)制,適用于可靠性比較高的局域網(wǎng)。由于 UDP采取 了無連接的方式,因此協(xié)議簡單,在一些特定的應(yīng)用中協(xié)議運(yùn)行效率高。 UDP 適合一些實(shí)時的應(yīng)用,如 IP 電話,視頻會議,它們要求源主機(jī)以恒定的速率 發(fā)送數(shù)據(jù),并且在網(wǎng)絡(luò)出現(xiàn)擁塞時,可以丟失一些數(shù)據(jù),但是延遲不能太大。 基于這些特點(diǎn)

2、,流式多媒體通信、多播等應(yīng)用在傳輸層采用的就是 UDP協(xié)議。因?yàn)閁DP具有TCP所望塵莫及的速度優(yōu)勢。雖然 TCP協(xié)議中植入了各種 安全保障功能,但是在實(shí)際執(zhí)行的過程中會占用大量的系統(tǒng)開銷,無疑使速 度受到嚴(yán)重的影響。反觀 UDP由于排除了信息可靠傳遞機(jī)制,將安全和排序 等功能移交給上層應(yīng)用來完成,極大降低了執(zhí)行時間,使速度得到了保證。、課程設(shè)計(jì)的內(nèi)容和要求編寫程序,設(shè)計(jì)UDP服務(wù)器。因?yàn)榭紤]到實(shí)時性,所以選擇 UDP為主要的網(wǎng)絡(luò)通信技術(shù)。(1) 程序能流暢地完成信息內(nèi)容的傳輸和接收。(2) 要能對多個客服端進(jìn)行管理。需要通過 UDP莫擬多個客服 端連接驗(yàn)證的情況。(3) 操作系統(tǒng)、使用語言和

3、編譯環(huán)境不限,但在作業(yè)中必須注 明。三、課程設(shè)計(jì)的相關(guān)技術(shù)(1) UDP 協(xié)議技術(shù)UDP是 一個無連接協(xié)議,傳輸數(shù)據(jù)之前源端和終端不建立連接,當(dāng)它想傳送時就簡單地去抓取來自應(yīng)用程序的數(shù)據(jù),并 盡可能快地把它扔到網(wǎng)絡(luò)上。在發(fā)送端, UDP傳送數(shù)據(jù)的速度 僅僅是受應(yīng)用程序生成數(shù)據(jù)的速度、 計(jì)算機(jī)的能力和傳輸帶寬 的限制;在接收端, UDP把每個消息段放在隊(duì)列中,應(yīng)用程序 每次從隊(duì)列中讀一個消息段。(2) C+編程技術(shù)(3) TCP/IP 協(xié)議技術(shù)在 T C P / I P 協(xié)議族中,有兩個互不相同的傳輸協(xié) 議:TCP (傳輸控制協(xié)議)和U D P (用戶數(shù)據(jù)報(bào)協(xié)議)。 T C P 為兩臺主機(jī)提供高

4、可靠性的數(shù)據(jù)通信。 它所做的工作包括 把應(yīng)用程序交給它的數(shù)據(jù)分成合適的小塊交給下面的網(wǎng)絡(luò)層,確 認(rèn)接收到的分組,設(shè)置發(fā)送最后確認(rèn)分組的超時時鐘等。由于運(yùn) 輸層提供了高可靠性的端到端的通信,因此應(yīng)用層可以忽略所有 這些細(xì)節(jié)。而另一方面,U D P則為應(yīng)用層提供一種非常簡單的服務(wù)。它只是把稱作數(shù)據(jù)報(bào)的分組從一臺主機(jī)發(fā)送到另一臺主 機(jī),但并不保證該數(shù)據(jù)報(bào)能到達(dá)另一端。任何必需的可靠性必須 由應(yīng)用層來提供。(4) TCP/IP 協(xié)議與 Winsock 網(wǎng)絡(luò)編程接口Winsock 規(guī)范不是一種網(wǎng)絡(luò)協(xié)議, 而是一套開放的、 支持多種 協(xié)議的Win dows寫的網(wǎng)絡(luò)編程接口。Win sock可以訪問很多種網(wǎng)

5、絡(luò) 協(xié)議,可以把它當(dāng)作一種協(xié)議的封裝?,F(xiàn)在的 Winsock 已經(jīng)基本 上實(shí)現(xiàn)了與協(xié)議無關(guān),可以使用 Win sock來調(diào)用協(xié)議的功能(5) Winsock API 的使用下面給出了使用 Win sock進(jìn)行編程時涉及的主要函數(shù):WSAStartup函數(shù)、WSACIeanu函數(shù)、socket 函數(shù) closesocket 函數(shù)、 send 函數(shù)、 recv 函數(shù)、 bind 函數(shù)、 listen 函數(shù)、 accept 函數(shù)、 connect 函數(shù)四、課程設(shè)計(jì)過程4.1 設(shè)計(jì)思路設(shè)計(jì)UDP服務(wù)器的過程如下所示。首先,創(chuàng)建又一個 Socket并監(jiān)聽。然后啟動線程接收數(shù)據(jù)。用一個鏈表保存所有連上的客

6、戶,并通知連接成功。這樣,客戶就有機(jī)會處理這一事件并作一些動作。最后,當(dāng)客戶斷開時,向服務(wù)器發(fā)送一個事件,服務(wù)器就可以做一些收 尾工作。其中最關(guān)鍵的部分是收發(fā)部分和數(shù)據(jù)處理部分。4.2 服務(wù)器的主要工作流程 如圖 1 所示:客戶機(jī)圖1服務(wù)器工作流程客戶機(jī)一方的工作流程如下:(1) 打開通信信道(申請一個套接字),并連接到服務(wù)器在主機(jī)的保 留端口,該端口對應(yīng)服務(wù)器的 UDP進(jìn)程。(2) 向服務(wù)器發(fā)出請求報(bào)文,等待接收應(yīng)答。(3) 從服務(wù)器方收到最終應(yīng)答結(jié)果,或在不再請求時關(guān)閉信道并終 止客戶機(jī)進(jìn)程。服務(wù)器一方的工作流程如下:(1) 打開通信信道 ( 申請一個套接字 ) ,通知本地主機(jī)在某一保留端

7、 口接收客戶機(jī)請求。(2) 等待客戶機(jī)請求到達(dá)指定端口。(3) 接收到請求,啟動一個新進(jìn)程處理用戶請求,同時釋放舊進(jìn)程 以響應(yīng)新的客戶請求,一旦服務(wù)完成,關(guān)閉新進(jìn)程與客戶的通 信鏈路。(4) 繼續(xù)等待客戶機(jī)請求。(5) 如果不想響應(yīng)客戶機(jī)請求,關(guān)閉服務(wù)器進(jìn)程。4.3 主要功能模塊 如下:(1) 發(fā)送BOOL CUdpSock:SendBuffer(char *buff, DWORD dwBufSize,struct sockaddr FAR *lpTo)m_lock.Lock();/ 鎖定WSABUF wsabuf;/建立結(jié)構(gòu)體WSAOVERLAPPED over建立結(jié)構(gòu)體DWORD dwre

8、cv;/定義DWORD dwFlags=0;/ 定義DWORD dwRet;/定義BOOL fPending;/ 定義int nRet;/ 定義/建立 WSABU和 WSAOVERLAPP兩個結(jié)構(gòu)體/memset(&over,0,sizeof(WSAOVERLAPPED); / 用給定字符填 充緩沖區(qū)wsabuf.buf = buff; / 緩沖區(qū)賦值wsabuf.len = dwBufSize; / 長度賦值 over.hEvent = WSACreateEvent(); / 創(chuàng)建事件fPending = FALSE; nRet = WSASendTo(m&wsabuf,1,

9、 /&dwRecv, dwFlags, lpTo, sizeof(sockaddr), &over,/NULL);/Socket, / 套接字/ 結(jié)構(gòu)體緩沖池參數(shù)/ 接受的字節(jié)數(shù)/ 標(biāo)記結(jié)構(gòu)體函數(shù)完成if (nRet != 0)int erro = WSAGetLastError();if (erro = WSA_IO_PENDING)fPending = TRUE; / 檢測是否是因?yàn)閭鬏斘赐瓿啥?造成的錯誤else TRACE1("CUdpSock:SendBuffer erro %dn",erro); / 給出出錯信息CloseHandle(over.

10、hEvent);return FALSE;/ 如果是 I/O 未完成/if (fPending)/ 等待完成請求或結(jié)束事件/dwRet = WaitForSingleObject(over.hEvent,60000);/ 判斷是否是接收方發(fā)出的信號/if (dwRet = WAIT_TIMEOUT)/WAIT_OBJECT_0/WAIT_TIMEOUTCloseHandle(over.hEvent); / 關(guān)閉一個內(nèi)核對象TRACE("WAIT_TIMEO發(fā)送失敗 n",NULL); / 提示發(fā) 送失敗return FALSE;/ 返回 if(dwRet!=WAIT_OBJ

11、ECT_0)/WAIT_OBJECT_0/WAIT_TIMEOUTCloseHandle(over.hEvent);/ 關(guān)閉一個內(nèi)核對象TRACE(發(fā)送失敗n",NULL);提示發(fā)送失敗 return FALSE;/ 返回/ 查看 I/O 信息/if (!WSAGetOverlappedResult(m_Socket,/ 套接字&over,&dwRecv,FALSE,&dwFlags)CloseHandle(over.hEvent);/ 關(guān)閉一個內(nèi)核對象TRACE("WSAGetOverlappedResult 發(fā) 送 失 敗 n",NUL

12、L);/ 提示發(fā)送失敗return FALSE;/ 返回CloseHandle(over.hEvent);/ 關(guān)閉一個內(nèi)核對象TRACE(發(fā)送成功n",NULL); 提示發(fā)送成功m_lock.Unlock();/ 解除鎖定return TRUE;/ 返回(2) 接收BOOLCUdpSock:RecvRequest(LPBYTEpBuf,DWORDdwBufSize,struct sockaddr FAR *lpFrom)/ 清空接收緩沖區(qū) memset(pBuf,0,dwBufSize);/ 建立 WSABU和 WSAOVERLAPF兩個結(jié)構(gòu)體wsabuf.buf=(char *)p

13、Buf;wsabuf.len=dwBufSize;memset(&over,0,sizeof(WSAOVERLAPPED); / 用給定的字符 串填充緩沖區(qū)over.hEvent=m_hEventSock;dwFlags=0;fPending=FALSE;int sizeAddr=sizeof(sockaddr_in); / 返回參數(shù)所占的字節(jié) 數(shù)nRet=WSARecvFrom( / 接受數(shù)據(jù) m_Socket,&wsabuf,1, &dwRecv, &dwFlags, lpFrom, &sizeAddr, &over, NULL);if(nR

14、et!=0)/ 判斷傳輸是否正常完成 if (WSAGetLastError() != WSA_IO_PENDING) return FALSE;else fPending = TRUE; / 如果完成 if(fPending)/ 等待結(jié)束請求或退出事件 hEvents0 = over.hEvent;hEvents1 = m_hEventExit; dwRet = WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);/ 判斷是否是接收方發(fā)出的信號/if (dwRet != 0) return FALSE; if (!WSAGetOverlap

15、pedResult(m_Socket,&over, &dwRecv, FALSE, &dwFlags) return FALSE;/ 接收結(jié)束/m_translate = dwRecv;return TRUE;(3) 數(shù)據(jù)處理部分BOOLCUdpSock:DelWithResData(struct sockaddr FAR*lpFrom) DWORD lenPag = sizeof(PackHead);DWORD start = 0;DWORD onePagLeft = 0;SockPags pags;if(m_bFillHead)/ 判斷緩沖區(qū)的長度 onePagLe

16、ft = m_PackHead.len - lenPag; if(m_SimpleIOBuffer.GetBufferLen() < onePagLeft) TRACE("There is no enough packege length! 1n");return FALSE;ASSERT(onePagLeft <= IOBUFFLEN); pags.buff = new charonePagLeft; if(m_SimpleIOBuffer.Read(pags.buff ,onePagLeft) pags.len = onePagLeft;pags.cm =

17、m_PackHead.cm; if(m_pResInterFace) m_pResInterFace->Excute(&pags,lpFrom); m_bFillHead = FALSE; DelWithResData(lpFrom);delete pags.buff;elsewhile(m_SimpleIOBuffer.Read(char*)&m_PackHead,lenPag )&&if(m_PackHead.ID0 != 'T' m_PackHead.ID1 != 'P') m_SimpleIOBuffer.Reset

18、(); m_bFillHead = FALSE; TRACE("There is packege2 is erro!n"); return FALSE;m_bFillHead = TRUE;onePagLeft = m_PackHead.len - lenPag; if(m_SimpleIOBuffer.GetBufferLen() onePagLeft)TRACE("There is no enough packege length! 2n");return FALSE;ASSERT(onePagLeft <= IOBUFFLEN);pags.b

19、uff = new charonePagLeft;if(m_SimpleIOBuffer.Read(pags.buff ,onePagLeft)pags.len = onePagLeft; pags.cm = m_PackHead.cm; if(m_pResInterFace) m_pResInterFace->Excute(&pags,lpFrom); m_bFillHead = FALSE;delete pags.buff;return TRUE;void CUdpSock:OnRead()m_translate=0; sockaddr_in addrfro; memset(

20、&addrfro,0,sizeof(sockaddr_in); addrfro.sin._family=AF_INET;/ 如果沒有接收請求就返回到讀信息函數(shù) if(!RecvRequest(LPBYTE)m_wsaInBuffer.buf, sizeof(m_byInBuffer),(sockaddr*)&addrfro)TRACE("CClientOverlappedSock:OnReadn");return;/ 如果 m_translate 不為 0,則向 m_SimpleIOBuffer 緩沖區(qū)寫信 息 if(m_translate)m_Simple

21、IOBuffer.Write(m_wsaInBuffer.buf,m_translate);try/ 處理收到的信息 DelWithResData(sockaddr*)&addrfro);catch(.)TRACE("Udp DelWithResData erro!n"); memset(&m_PackHead,0,sizeof(PackHead); m_bFillHead=FALSE;m_SimpleIOBuffer.Notify();return;一, 注意有一個緩沖區(qū) m_SimpleIOBuffer 主要用來保證每次 收發(fā)的完整性。然后就是C+異常機(jī)

22、制,主要是為了穩(wěn)定性。二, 在 CUdpSock:DelWithResData 的處理部分,有很多保護(hù)措施。這很重要。然后從CUdpSoc派生一個CSverUdpSock如下:#inClude "UdpSoCk.h"#include "ClientUdpConnect.h"#include "afxtempl.h"class CSverUdpSock : public CUdpSockpublic:virtual void Close();int GetClientCount();CClientUdpConnect* GetClien

23、t(struct sockaddr FAR *lpFrom);virtual void OnRead();virtual void OnAccept(struct sockaddr FAR *lpFrom);virtual void ShutDown(struct sockaddr FAR *lpFrom);virtual void ShutDown(CClientUdpConnect *_pClient);virtual void OnShutDown(struct sockaddr FAR *lpFrom);void CloseAllClients();CSverUdpSock();vir

24、tual CSverUdpSock();CObList m_clients;CObList m_willbedeleteclients;CCriticalSection m_lockFreeClients;private:virtual BOOL Accept(struct sockaddr FAR *lpFrom);BOOL IsAlreadyExit(struct sockaddr FAR *lpFrom);CCriticalSection m_lockClients;CEvent m_timer;protected:void AddDeathClient(CClientUdpConnec

25、t *_pClient);void FreeClients();4.4 程序?qū)崿F(xiàn)部分 如下:(1) 客戶端程序如下:#include <winsock2.h>#include <stdio.h>#pragma comment(lib, "WS2_32") /鏈接到 WS2_32.libBOOL InitWinsock();/ 初始化 winsockvoid main()SOCKET socket1; / 定義套接字InitWinsock();/ 初始化 winsockstruct sockaddr_in server; /定義結(jié)構(gòu)體int len =

26、sizeof(server); /定義結(jié)構(gòu)體的長度server.sin_family=AF_INET; /server的地址族server.sin_port=htons(1000);/server 的監(jiān)聽端口 server.sin_addr.s_addr=inet_addr("172.16.93.187");/server 的地址socket1=socket(AF_INET,SOCK_DGRAM,0); / 給套接字賦值 while (1) / 使可以循環(huán)輸入char buffer1024="0" /定義緩沖區(qū)printf("input mes

27、sagen"); / 提示輸入 scanf("%s",buffer); / 輸入 if (strcmp(buffer,"bye")=0) / 比較字符串 break;if (sendto(socket1,buffer,sizeof buffer,0,(struct sockaddr*)&server,len)!=SOCKET_ERROR) / 發(fā)送數(shù)據(jù)if (recvfrom(socket1,buffer,sizeof buffer,0,(struct sockaddr*)&server,&len)!=SOCKET_ER

28、ROR) / 接受數(shù)據(jù)printf("rece from server:%sn",buffer);closesocket(socket1); / 關(guān)閉套接字BOOL InitWinsock()int Error;WORD VersionRequested;/ 版本號WSADATA WsaData;VersionRequested=MAKEWORD(2,2); /版本 2的套接字 Error=WSAStartup(VersionRequested,&WsaData); / 啟 動 WinSock2if(Error!=0)return FALSE; / 加載套接字庫 失

29、敗則返回elseif(LOBYTE(WsaData.wVersion)!=2|HIBYTE(WsaData.wHighV ersion)!=2) / 判斷版本W(wǎng)SACleanup(); / 解除綁定并釋放空間 return FALSE;return TRUE;/ 如果不是版本 2 則退出(2) 服務(wù)器端程序如下#include <winsock2.h>#include <stdio.h>#pragma comment(lib, "WS2_32") /鏈接到 WS2_32.libBOOL InitWinsock();void main()SOCKET

30、socket1;/ 定義套接字InitWinsock();struct sockaddr_in local;struct sockaddr_in from;int fromlen =sizeof(from);local.sin_family=AF_INET;local.sin_port=htons(1000); / 監(jiān)聽端口 local.sin_addr.s_addr=INADDR_ANY; / 本機(jī)socket1=socket(AF_INET,SOCK_DGRAM,0);bind(socket1,(struct sockaddr*)&local,sizeof local);while

31、 (1)char buffer1024="0"printf("waiting for message fromothersn");if (recvfrom(socket1,buffer,sizeofbuffer,0,(struct sockaddr*)&from,&fromlen)!=SOCKET_ERROR) printf("Received datagram from %s-%sn",inet_ntoa(from.sin_addr),buffer);/ 給 cilent 發(fā)信息 sendto(socket1,buf

32、fer,sizeof buffer,0,(structsockaddr*)&from,fromlen);Sleep(500);closesocket(socket1);BOOL InitWinsock()int Error;WORD VersionRequested;WSADATA WsaData;VersionRequested=MAKEWORD(2,2);Error=WSAStartup(VersionRequested,&WsaData); / 啟 動 WinSock2if(Error!=0)return FALSE;elseif(LOBYTE(WsaData.wVersion)!=2|HIBYTE(WsaData.wHighV ersion)!=2)WSACleanup(); return FALSE;return TRUE;4.

溫馨提示

  • 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

提交評論