版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
38/38信息通信網(wǎng)絡(luò)概論實驗指導書
目錄實驗一TCP/IP協(xié)議與Socket編程認識實驗 4一、 實驗?zāi)康?4二、 實驗內(nèi)容 4三、 實驗原理 4四、 實驗步驟 5五、 思考題或討論題 6實驗二FTP客戶端通信程序設(shè)計 7一、 實驗?zāi)康?7二、 實驗內(nèi)容 7三、 實驗原理 7四、 思考題或討論題 9實驗三基于客戶/服務(wù)器模式的網(wǎng)絡(luò)通信編程實現(xiàn) 11一、 實驗?zāi)康?11二、 實驗內(nèi)容 11三、 實驗原理 11四、 應(yīng)用程序的設(shè)計方法和步驟 12五、 聊天室應(yīng)用程序設(shè)計的具體說明 141、聊天室的工作流程 142、套接字事件處理 153、系統(tǒng)實現(xiàn) 163.1利用MFCAppWizard生成程序框架 163.2增加控件對象 163.3從CAsyncSocket類繼承 163.4建立客戶機與服務(wù)器之間的連接 163.5發(fā)送和接收數(shù)據(jù) 173.6終止連接 174、結(jié)束語 17六、 思考題或討論題 18實驗四﹑計算機網(wǎng)絡(luò)通信應(yīng)用程序設(shè)計 19(一)基于TCP/IP的計算機網(wǎng)絡(luò)通信應(yīng)用程序設(shè)計 19一、 實驗?zāi)康?19二、 實驗內(nèi)容 19三、 實驗步驟 19(二)基于UDP/IP的計算機網(wǎng)絡(luò)通信應(yīng)用程序設(shè)計 20一、 實驗?zāi)康?20二、 實驗內(nèi)容 20三、 實驗步驟 21四、 思考題或討論題 21附錄:實驗中需要用到的WINSOCKAPI函數(shù)和數(shù)據(jù)結(jié)構(gòu) 22accept(): 22bind() 23closesocket(): 24connect(): 26listen(): 27socket(): 28recv(): 29send(): 31WSAAsyncSelect(): 32WSAStartup(): 36Gethostbyname 37Gethostbyaddr 38inet_ntoa 38inet_addr 38WSADATA和LPWSADATA 38
實驗一TCP/IP協(xié)議與Socket編程認識實驗實驗?zāi)康氖煜CP/IP協(xié)議的功能和網(wǎng)絡(luò)操作;了解基于SOCKET的編程原理;編寫一個小型的Socket實用程序,初步了解Windows環(huán)境下使用Socket的編程。實驗內(nèi)容在已有的程序框架下,編寫一個查詢主機地址和域名的程序。實現(xiàn)功能:輸入域名查詢IP地址;輸入IP地址查詢域名。實驗原理什么是WindowsSockets規(guī)范?WindowsSockets規(guī)范以U.C.Berkeley大學BSDUNIX中流行的Socket接口為范例定義了一套MicosoftWindows下網(wǎng)絡(luò)編程接口。它不僅包含了人們所熟悉的BerkeleySocket風格的庫函數(shù);也包含了一組針對Windows的擴展庫函數(shù),以使程序員能充分地利用Windows消息驅(qū)動機制進行編程。WindowsSockets規(guī)范本意在于提供給應(yīng)用程序開發(fā)者一套簡單的API,并讓各家網(wǎng)絡(luò)軟件供應(yīng)商共同遵守。此外,在一個特定版本W(wǎng)indows的基礎(chǔ)上,WindowsSockets也定義了一個二進制接口(ABI),以此來保證應(yīng)用WindowsSocketsAPI的應(yīng)用程序能夠在任何網(wǎng)絡(luò)軟件供應(yīng)商的符合WindowsSockets協(xié)議的實現(xiàn)上工作。因此這份規(guī)范定義了應(yīng)用程序開發(fā)者能夠使用,并且網(wǎng)絡(luò)軟件供應(yīng)商能夠?qū)崿F(xiàn)的一套庫函數(shù)調(diào)用和相關(guān)語義。遵守這套WindowsSockets規(guī)范的網(wǎng)絡(luò)軟件,我們稱之為WindowsSockets兼容的,而WindowsSockets兼容實現(xiàn)的提供者,我們稱之為WindowsSockets提供者。一個網(wǎng)絡(luò)軟件供應(yīng)商必須百分之百地實現(xiàn)WindowsSockets規(guī)范才能做到現(xiàn)WindowsSockets兼容。任何能夠與WindowsSockets兼容實現(xiàn)協(xié)同工作的應(yīng)用程序就被認為是具有WindowsSockets接口。我們稱這種應(yīng)用程序為WindowsSockets應(yīng)用程序。WindowsSockets規(guī)范定義并記錄了如何使用API與Internet協(xié)議族(IPS,通常我們指的是TCP/IP)連接,尤其要指出的是所有的WindowsSockets實現(xiàn)都支持流套接口和數(shù)據(jù)報套接口.應(yīng)用程序調(diào)用WindowsSockets的API實現(xiàn)相互之間的通訊。WindowsSockets又利用下層的網(wǎng)絡(luò)通訊協(xié)議功能和操作系統(tǒng)調(diào)用實現(xiàn)實際的通訊工作。它們之間的關(guān)系如圖1-1。Winsock編程模型建立socket。程序使用socket進行網(wǎng)絡(luò)時,必須先建立一個socket。為了建立一個socket,成需要調(diào)用socket函數(shù)。例子:socket_handle=socket(protocol_family,_socket_type,protocol);配置一個socket。為了配置一個,程序可使用WinsockAPI中不同的函數(shù)。一般來講,每個socket需要五種信息:本地和遠地機的IP地址,本地和遠地進程的協(xié)議端口,聯(lián)接上使用的協(xié)議。連接一個socket。面向連接客戶程序必須提供給Socket的唯一地址信息是遠地主機信息—IP地址和協(xié)議端口。使用一個Socket,程序能夠使用WinsockAPI在一個配置好的Socket上傳送和接收數(shù)據(jù)。I/O函數(shù)如下:Send,通過連接的Socket傳送數(shù)據(jù),使用特殊的標志控制Socket的行為。Sendto,將數(shù)據(jù)傳送給Socket地址結(jié)構(gòu)指定的主機,傳送時使用一個簡單的報文緩沖區(qū)。Recvfrom,從Socket接收數(shù)據(jù),選擇發(fā)送主機的網(wǎng)絡(luò)地址,傳送時使用一個簡單的報文緩沖區(qū)。使用一個連接的Socket。由于Send函數(shù)不能指定目的地址,因此,程序只能在連接的Socket上使用它。也就是說,在程序使用Send函數(shù)之前,必須建立一個Socket。使用一個無連接的Socket。當沒有建立Socket連接時,上述的Send函數(shù)便不能使用,這是需要用Sendto函數(shù)。實驗步驟網(wǎng)絡(luò)程序初始化,服務(wù)器和客戶端WinSockAPI均要求在調(diào)用其他WinSock函數(shù)以前先調(diào)用WSAStartUp函數(shù)初始化。創(chuàng)建套接字Socket()。配置并啟動套接字。通過Socket發(fā)送和接收數(shù)據(jù)。程序結(jié)束時必須關(guān)閉Socket,使用與WSAStartUp()相對應(yīng)的函數(shù)WSACleanUp(),釋放所分配的內(nèi)部緩沖區(qū)和其他資源。思考題或討論題1.WinInet有什么作用?2.結(jié)合本次實驗,談?wù)勈褂肕FCWinInet類有哪些優(yōu)點?
實驗二FTP客戶端通信程序設(shè)計實驗?zāi)康牧私釽indows下的TCP/IP通信方式與網(wǎng)絡(luò)操作熟悉FTP的編程的過程;學會用可視化編程語言編寫調(diào)試簡單的通信程序。實驗內(nèi)容在已有的程序框架下,編寫一個FTP客戶端程序。實現(xiàn)功能:連接到FTP主機,下載FTP文件服務(wù)器文件列表;切換訪問目錄;向FTP服務(wù)器發(fā)送文件(上傳文件);從FTP服務(wù)器下載文件(下載文件)。實驗原理在使用MFC編程時,要連接到FTP服務(wù)器是一件非常簡單的事情,只需要兩個簡單的步驟,首先必須建立一個CinternetSession對象,用類CinternetSession創(chuàng)建并初始化一個或幾個同時存在的Internet會話(Session),并描述與代理服務(wù)器的連接(如果有必要的話),如果在程序運行期間需要保持與Internet的廉潔,可以創(chuàng)建一個CinternetSession對象作為類CwinApp的成員。MFC中的類C管理我們與Internet服務(wù)器的連接,并直接操作服務(wù)器上的目錄和文件,的WinInet支持的三個Internet功能之一,我們需要先創(chuàng)建一個CinternetSession實例和一個C對象就可以實現(xiàn)和一個FTP服務(wù)器通信,我們不需要直接創(chuàng)建C對象,而是通過調(diào)用CinternetSession::Get來完成這項工作。他創(chuàng)建C對象并返回一個指向該對象的指針。在FTP連接的程序中,主要適用下列7個函數(shù):CInternetSession對象語法:CInternetSession(LPCTSTRpstrAgent,DWORDdwConText,DWORDdwAccessType,LPCTSTRpstrProxyName,LPCTSTRpstrProxyBypass,DWORDdwFlags);注釋:在創(chuàng)建CInternetSession對象時調(diào)用這個成員函數(shù),CInternetSession是應(yīng)用程序第一個要調(diào)用的Internet函數(shù),它將創(chuàng)始化內(nèi)部數(shù)據(jù)結(jié)構(gòu),以備將來在應(yīng)用程序中調(diào)用。如果dwFlags包含INTERNET_FLAG_ASYNC,那末從這個句柄派生的所有的句柄,在狀態(tài)回調(diào)例程注冊之前,都會出現(xiàn)異步狀態(tài)。如果沒有打開Internet連接,CInternetSession就會拋出一個例外,fxThorowInternetException。Get()函數(shù)。語法:C*CIternetSession::Get(LPCTSTRpstrServer,LPCTSTRpstrUserName,LPCTSTRpstrPassword,INTERNET_PORTnPort,BOOLbPassive);注釋:調(diào)用這個函數(shù)建立一個FTP連接,并獲得一個指向C對象的指針,Get連接到一個FTP服務(wù)器,創(chuàng)建并返回指向C對象的指針,它不在服務(wù)器上進行任何操作。如果打算讀寫文件,必須進行分步操作。關(guān)于查找,打開和讀/寫文件的信息需參考C和C類。對這個函數(shù)的調(diào)用返回一個指向C對象的指針。如果調(diào)用失敗,檢查拋出的CInternetException對象,就可以確定失敗的原因。GetFile()函數(shù)。語法:BOOLGetpstrRemotepstrLocalbFailExists,DWORDdwAttributes,DWORDdwFlags,DWORDdwContext);注釋:調(diào)用這個成員函數(shù),可以從FTP服務(wù)器取得文件,并且把文件保存在本地機器上。GetFile()函數(shù)是一個比較高級的例程,它可以處理所有有關(guān)從FTP服務(wù)器讀文件,以及把文件存放在本地機器上的工作。如果dwFlags為,文件數(shù)據(jù)的傳輸也會把控制和格式符轉(zhuǎn)化為Windows中的等階符號。默認的傳輸模式是二進制模式,文件會以和服務(wù)器上相同的格式被下載。pstrRemoteFile和pstrLocalFile可以是相對于當前目錄的部分文件名,也可以是全文件名,在這兩個名字中間,都既可以用反斜杠(\)或者正斜杠(/)來作為文件名的目錄分隔符,GetFile()在使用前會把目錄分隔符轉(zhuǎn)化為適當?shù)淖址?。可以用自己選擇的值來取代dwContext默認的值,設(shè)置為上下文標識符與C對象的定位操作有關(guān),這個操作由C中的CInternetSession對象創(chuàng)建。返回給CInternetSession::OnStatusCallBack的值指出了所標識操作的狀態(tài)。如果調(diào)用成功,函數(shù)的返回為非0,否則返回0,如果調(diào)用失敗,可以調(diào)用Win32函數(shù)GetLastError(),確認出錯的原因。PutFile()函數(shù)。語法:BOOLPutpstrLocalFile,LPCTSTRpstrRemovedwFlags,DWORDdwContext);注釋:調(diào)用這個成員函數(shù)可以把文件保存到FTP服務(wù)器。PutFile()函數(shù)是一個比較高級的例程,它可以處理有關(guān)把文件存放到服務(wù)器上的工作。只發(fā)送數(shù)據(jù),或要嚴格控制文件傳輸?shù)膽?yīng)用程序,應(yīng)該調(diào)用OpenFile和CInternet::Write。利用自己選擇的值來取代dwContext默認的值,設(shè)置為上下文標識符,上下文標識符是CInternetSession對象創(chuàng)建的C對象的特定操作有關(guān),這個值返回給CInternetSession::OnStateCallBack,從而把操作的狀態(tài)通報給它所標識的上下文。如果調(diào)用成功,函數(shù)的返回為非0,否則返回0,如果調(diào)用失敗,可以調(diào)用Win32函數(shù)GetLastError(),確認出錯的原因。FTP文件查找函數(shù)。調(diào)用這個成員函數(shù)構(gòu)造一個C對象。FindFile()函數(shù)。調(diào)用這個函數(shù)查找FTP文件,調(diào)用它檢索到第一個FTP文件后,可以調(diào)用FindNextFile()檢索后面的FTP文件。FindNextFile()函數(shù)。調(diào)用這個函數(shù)繼續(xù)查找文件,在調(diào)用任何屬性以前,必須已經(jīng)至少調(diào)用過一次此函數(shù)。以上函數(shù)的具體使用方法可以參見MSDN。思考題或討論題1.WinInet有什么作用?2.結(jié)合本次實驗,談?wù)勈褂肕FCWinInet類有哪些優(yōu)點?
實驗三基于客戶/服務(wù)器模式的網(wǎng)絡(luò)通信編程實現(xiàn)(基于Socket的網(wǎng)絡(luò)聊天室的設(shè)計與實現(xiàn))實驗?zāi)康倪M一步了解網(wǎng)絡(luò)編程的過程;掌握Windows環(huán)境下基于WinSock的編程方法和通信實現(xiàn);熟悉客戶/服務(wù)器模式的網(wǎng)絡(luò)通信編程實現(xiàn),編寫一個聊天工具,即以客戶端和服務(wù)器端的模式進行互發(fā)消息。實驗內(nèi)容Internet上可以提供一種叫IRC的服務(wù)。使用者通過客戶端的程序登錄到IRC服務(wù)器上,就可以與登錄在同一IRC服務(wù)器上的客戶進行交談,這也就是平常所說的聊天室。在已有的程序框架下,編寫一個類似的聊天程序。實現(xiàn)功能:服務(wù)器端:建立Socket,綁定端口,并監(jiān)聽;接受客戶端的連接;與客戶端進行通訊;斷開連接??蛻舳耍航ocket,并申請連接到服務(wù)器;與服務(wù)器進行通訊;斷開連接。實驗原理一個在建立分布式應(yīng)用時最常用的范例便是客戶機/服務(wù)器模型。在這種方案中客戶應(yīng)用程序向服務(wù)器程序請求服務(wù)。這種方式隱含了在建立客戶機/服務(wù)器間通訊時的非對稱性??蛻魴C/服務(wù)器模型工作時要求有一套為客戶機和服務(wù)器所共識的慣例來保證服務(wù)能夠被提供(或被接受)。這一套慣例包含了一套協(xié)議。它必須在通訊的兩頭都被實現(xiàn)。根據(jù)不同的實際情況,協(xié)議可能是對稱的或是非對稱的。在對稱的協(xié)議中,每一方都有可能扮演主從角色;在非對稱協(xié)議中,一方被不可改變地認為是主機,而另一方則是從機。一個對稱協(xié)議的例子是Internet中用于終端仿真的TELNET。而非對稱協(xié)議的例子是Internet中的FTP。無論具體的協(xié)議是對稱的或是非對稱的,當服務(wù)被提供時必然存在“客戶進程”和“服務(wù)進程”。一個服務(wù)程序通常在一個眾所周知的地址監(jiān)聽對服務(wù)的請求,也就是說,服務(wù)進程一直處于休眠狀態(tài),直到一個客戶對這個服務(wù)的地址提出了連接請求。在這個時刻,服務(wù)程序被“驚醒”并且為客戶提供服務(wù)-對客戶的請求作出適當?shù)姆磻?yīng)。這一請求/相應(yīng)的過程可以簡單的用圖2-1表示。雖然基于連接的服務(wù)是設(shè)計客戶機/服務(wù)器應(yīng)用程序時的標準,但有些服務(wù)也是可以通過數(shù)據(jù)報套接口提供的。應(yīng)用程序的設(shè)計方法和步驟服務(wù)端建立Socket初始化WinSock的動態(tài)連接庫后,需要在服務(wù)器端建立一個監(jiān)聽的Socket,為此可以調(diào)用Socket()函數(shù)用來建立這個監(jiān)聽的Socket,并定義此Socket所使用的通信協(xié)議。此函數(shù)調(diào)用成功返回Socket對象,失敗則返回INVALID_SOCKET(調(diào)用WSAGetLastError()可得知原因,所有WinSocket的函數(shù)都可以使用這個函數(shù)來獲取失敗的原因)。綁定端口接下來要為服務(wù)器端定義的這個監(jiān)聽的Socket指定一個地址及端口(Port),這樣客戶端才知道待會要連接哪一個地址的哪個端口,為此我們要調(diào)用bind()函數(shù),該函數(shù)調(diào)用成功返回0,否則返回SOCKET_ERROR。監(jiān)聽當服務(wù)器端的Socket對象綁定完成之后,服務(wù)器端必須建立一個監(jiān)聽的隊列來接收客戶端的連接請求。listen()函數(shù)使服務(wù)器端的Socket進入監(jiān)聽狀態(tài),并設(shè)定可以建立的最大連接數(shù)(目前最大值限制為5,最小值為1)。該函數(shù)調(diào)用成功返回0,否則返回SOCKET_ERROR。服務(wù)器端的Socket調(diào)用完listen()后,如果此時客戶端調(diào)用connect()函數(shù)提出連接申請的話,Server端必須再調(diào)用accept()函數(shù),這樣服務(wù)器端和客戶端才算正式完成通信程序的連接動作。為了知道什么時候客戶端提出連接要求,從而服務(wù)器端的Socket在恰當?shù)臅r候調(diào)用accept()函數(shù)完成連接的建立,我們就要使用WSAAsyncSelect()函數(shù),讓系統(tǒng)主動來通知我們有客戶端提出連接請求了。該函數(shù)調(diào)用成功返回0,否則返回SOCKET_ERROR。服務(wù)器端接受客戶端的連接請求當Client提出連接請求時,Server端hwnd視窗會收到WinsockStack送來我們自定義的一個消息,這時,我們可以分析lParam,然后調(diào)用相關(guān)的函數(shù)來處理此事件。為了使服務(wù)器端接受客戶端的連接請求,就要使用accept()函數(shù),該函數(shù)新建一Socket與客戶端的Socket相通,原先監(jiān)聽之Socket繼續(xù)進入監(jiān)聽狀態(tài),等待他人的連接要求。該函數(shù)調(diào)用成功返回一個新產(chǎn)生的Socket對象,否則返回INVALID_SOCKET。結(jié)束socket連接結(jié)束服務(wù)器和客戶端的通信連接是很簡單的,這一過程可以由服務(wù)器或客戶機的任一端啟動,只要調(diào)用closesocket()就可以了,而要關(guān)閉Server端監(jiān)聽狀態(tài)的socket,同樣也是利用此函數(shù)??蛻舳丝蛻舳吮容^簡單,只有一個socket,與服務(wù)端進行連接。連接建立好后,通過此SOCKET發(fā)送和接收信息。建立客戶端的Socket客戶端應(yīng)用程序首先也是調(diào)用WSAStartup()函數(shù)來與Winsock的動態(tài)連接庫建立關(guān)系,然后同樣調(diào)用socket()來建立一個TCP或UDPsocket(相同協(xié)定的sockets才能相通,TCP對TCP,UDP對UDP)。與服務(wù)器端的socket不同的是,客戶端的socket可以調(diào)用bind()函數(shù),由自己來指定IP地址及port號碼;但是也可以不調(diào)用bind(),而由Winsock來自動設(shè)定IP地址及port號碼。提出連接申請客戶端的Socket使用connect()函數(shù)來提出與服務(wù)器端的Socket建立連接的申請,函數(shù)調(diào)用成功返回0,否則返回SOCKET_ERROR。數(shù)據(jù)的傳送雖然基于TCP/IP連接協(xié)議(流套接字)的服務(wù)是設(shè)計客戶機/服務(wù)器應(yīng)用程序時的主流標準,但有些服務(wù)也是可以通過無連接協(xié)議(數(shù)據(jù)報套接字)提供的。介紹一下TCPsocket與UDPsocket在傳送數(shù)據(jù)時的特性:Stream(TCP)Socket提供雙向、可靠、有次序、不重復的資料傳送。Datagram(UDP)Socket雖然提供雙向的通信,但沒有可靠、有次序、不重復的保證,所以UDP傳送數(shù)據(jù)可能會收到無次序、重復的資料,甚至資料在傳輸過程中出現(xiàn)遺漏。由于UDPSocket在傳送資料時,并不保證資料能完整地送達對方,所以絕大多數(shù)應(yīng)用程序都是采用TCP處理Socket,以保證資料的正確性。一般情況下TCPSocket的數(shù)據(jù)發(fā)送和接收是調(diào)用send()及recv()這兩個函數(shù)來達成,而UDPSocket則是用sendto()及recvfrom()這兩個函數(shù),這兩個函數(shù)調(diào)用成功發(fā)揮發(fā)送或接收的資料的長度,否則返回SOCKET_ERROR。聊天室應(yīng)用程序設(shè)計的具體說明1、聊天室的工作流程Socket()Socket()Bind()Listen()服務(wù)器偵聽套接字Connect()Accept()Closesocket()Send()Recv()創(chuàng)建連接套接字客戶機連接套接字Socket()Bind()Recv()Send()Closesocket()Closesocket()首先,服務(wù)器要創(chuàng)建一個用于偵聽的套接字,為該套接字分配地址之后,調(diào)用listen()函數(shù)使它處于偵聽狀態(tài);客戶機在創(chuàng)建套接字完畢后,為套接字分配地址,然后調(diào)用connect()函數(shù),請求與服務(wù)器套接字連接;服務(wù)器套接字在收到客戶機的連接請示后,調(diào)用accept()函數(shù),該函數(shù)創(chuàng)建一個用于連接的套接字。應(yīng)用該套接字和客戶機上的連接套接字,用戶就可以在服務(wù)器和客戶機之間進行數(shù)據(jù)傳輸了。在結(jié)束傳輸之后,客戶機調(diào)用closesocket()函數(shù)關(guān)閉套接字,服務(wù)器也調(diào)用該函數(shù)關(guān)閉用于偵聽和連接的套接字。2、套接字事件處理消息處理函數(shù),這些函數(shù)并不對套接字作實質(zhì)上的操作,是Windows為套接字加上消息驅(qū)動的產(chǎn)物。它們和特定的套接字消息相關(guān)聯(lián),當消息到來時,應(yīng)用程序框架就調(diào)用這些函數(shù)。它們都是CAsyncSocket類的虛函數(shù),因為MFC庫中沒有定義這些函數(shù)的內(nèi)容,程序員必須根據(jù)需要重載這些函數(shù),把對套接字進行實質(zhì)操作的函數(shù)加進這些函數(shù)中。OnAccept():監(jiān)聽套接字在斷口聽到連接請求時,應(yīng)用程序框架調(diào)用該函數(shù)以告之可以接受或拒絕連接請求,調(diào)用Accept來接受請求,建立連接。OnConnect():當客戶端套接字連接請求完成后,應(yīng)用程序框架調(diào)用該函數(shù),告之是否成功。OnSend():框架調(diào)用該函數(shù)通知該套接字現(xiàn)在可以調(diào)用Send函數(shù)開始傳送數(shù)據(jù)。OnReceive():框架調(diào)用該函數(shù)通知套接字可以調(diào)用Receive函數(shù)從數(shù)據(jù)緩沖區(qū)中取數(shù)據(jù)。OnClose():框架調(diào)用該函數(shù)告之與其相連的對方套接字已被關(guān)閉。3、系統(tǒng)實現(xiàn)3.1利用MFCAppWizard生成程序框架在VisualC++的IDE環(huán)境下選擇菜單File—New—Projects—MFCAppWizard(exe)—ProjectName—“OK”—“NEXT”—WindowsSockets—“Finish”按鈕,選擇“OK”按鈕,應(yīng)用程序的框架就將自動創(chuàng)建。3.2增加控件對象在創(chuàng)建了應(yīng)用程序框架之后,可以布置程序的主對話框,向應(yīng)用程序的主對話框添加控件。設(shè)計好了對話框之后,選取View菜單中的ClassWizard菜單項,或直接按“Ctrl+W”,打開MFCClassWizard,將對話框中的控件和變量相關(guān)聯(lián),其關(guān)系如下表所示。變量說明表對象名稱類別類別IDC_BTN_CONNECTm_btnConnectControlCButtonIDC_COMBO_TYPEm_cmbTypeControlCComboBoxIDC_EDIT_MSGm_strMsgValueCStringIDC_EDIT_SERVNAMEm_strServNameValueCStringIDC_EDIT_SERVPORTm_nSerPortValueIntIDC_LIST_RECEIVEDm_listReceivedControlCListBoxIDC_LIST_SENTm_listSentControlCListBox3.3從CAsyncSocket類繼承選擇Insert菜單中的NewClass——選取Classtype為GenericClass——在Baseclass的DerivedFrom列中輸入CAsyncSocket,——在As列中接受默認值public,點擊”O(jiān)K”按鈕,就可以把這個新創(chuàng)建的類添加到應(yīng)用程序中。向該套接字類中添加一個成員變量,用作指向父對話框窗口的指針,指針變量的類型為CTalkDlg*(Cdialog的派生類),變量名為m_pDlg,訪問權(quán)限為私有。最后,添加套接字類事件處理函數(shù),這些函數(shù)將用于調(diào)用對話框中名稱類似的那些函數(shù)。3.4建立客戶機與服務(wù)器之間的連接為了完成連接,需要添加對套接字事件的處理函數(shù),在對話框類中添加OnAccept()事件處理函數(shù)和OnConnect()事件處理函數(shù)。如果現(xiàn)在可以編譯和運行應(yīng)用程序,就可以啟動兩個副本,把其中一個設(shè)置為偵聽模式,然后把另一個應(yīng)用程序與之相連接。為此,先向?qū)υ捒蝾?)添加三個成員函數(shù),這三個函數(shù)是套接字類()的事件處理函數(shù)需要調(diào)用的。把三個函數(shù)的類型都指定為void,訪問權(quán)限為公共。指定第一個函數(shù)聲明為OnSend(),第二個函數(shù)的聲明為OnReceive,第三函數(shù)的聲明為OnClose。3.5發(fā)送和接收數(shù)據(jù)如果兩個應(yīng)用程序間建立了連接,用戶就能夠在對話框窗口中的編輯框中輸入文本消息,然后單擊“發(fā)送”按鈕,就應(yīng)該可以把消息發(fā)送到另一個應(yīng)用程序,一旦消息發(fā)送出去了,它將被添加到已發(fā)送消息的列表框中。當“發(fā)送”按鈕被單擊之后,應(yīng)用程序需要檢查是否有消息輸入了編輯框,獲取該消息的長度,并發(fā)送該消息,然后把此消息添加到列表框中。為了在應(yīng)用程序中添加此項功能,使用ClassWizard向“發(fā)送”按鈕(ID:IDOK)的單擊事件(BN—CLICKED)添加一個事件處理函數(shù),注意不要接受默認的函數(shù)名,將函數(shù)名改成OnSendMsg(),編輯該函數(shù)。對于消息的接收方,當套接字的OnReceive事件被觸發(fā)時,表明一個消息已經(jīng)到達了,可以用Receive()函數(shù)從套接字檢索到該消息。如果消息被順利檢索到,需要把接收的字符數(shù)組轉(zhuǎn)換成Cstring類型,并把接收的消息添加到已接收的消息的列表框中。通過編輯對話框類(CtalkDlg)的OnReceive()函數(shù)。3.6終止連接結(jié)束消息傳送之后應(yīng)該終止兩個應(yīng)用程序之間的連接,這個終止連接的操作是由客戶機應(yīng)用程序的用戶通過單擊“斷開”按鈕來實現(xiàn)的。然后應(yīng)用程序會接收到一個OnClose套接字事件。和建立連接的過程相反,連接的套接字需要斷開,發(fā)送消息的控件需要置為禁用狀態(tài)。在客戶端,“連接”按鈕控件由禁用狀態(tài)變成可用,因為應(yīng)用程序允許客戶機程序改變某些參數(shù),并打開與另一個服務(wù)器程序的連接。同時,服務(wù)器應(yīng)用程序繼續(xù)偵聽是否有其他的連接請求,偵聽的端口等信息不變。4、結(jié)束語這個應(yīng)用程序在MFCWinSock編程中很有代表性,可以用于兩臺計算機之間進行字符串傳輸;創(chuàng)建思路簡單,就是利用MFCAppWizard生成程序框架,通過對CAsynSocket類增加一個指向?qū)υ捒蝾惖弥羔?,對CAsynSocket類中的一些事件處理函數(shù)進行重載,使這些套接字事件發(fā)生時,應(yīng)用程序能夠自動到對話框類中尋找合適的函數(shù)執(zhí)行。這個聊天室應(yīng)用程序是基于客戶/服務(wù)器模型的,一個服務(wù)器只能支持一個客戶,因此它實際上是一個基于“點對點”模型的應(yīng)用程序。通過這個應(yīng)用程序,用戶可以在兩臺計算機之間進行字符串傳輸——即可以為兩個人進行網(wǎng)上聊天提供服務(wù),而且兩個人的傳輸?shù)淖址槐A粼诔绦虻牧斜砜蛑?,并且進行分類,分為傳送和接收的字符串。思考題或討論題1.本次實驗所涉及的“實體”是什么?實體間通過什么方式建立協(xié)議?2.服務(wù)和協(xié)議的區(qū)別與聯(lián)系?本次實驗的協(xié)議過程(即客戶-服務(wù)器方式)是怎樣建立的?有哪些服務(wù)?3、本次實驗的協(xié)議提供了什么服務(wù)?試想,用此協(xié)議還可以提供怎樣的服務(wù)?這種服務(wù)在自動化學科領(lǐng)域的意義是什么?實驗四﹑計算機網(wǎng)絡(luò)通信應(yīng)用程序設(shè)計(一)基于TCP/IP的計算機網(wǎng)絡(luò)通信應(yīng)用程序設(shè)計實驗?zāi)康?.通過本實驗課程的學習,使學生能夠理解TCP協(xié)議通信的基本原理。2.通過運用WinSock接口編寫網(wǎng)絡(luò)通信應(yīng)用程序,掌握TCP網(wǎng)絡(luò)應(yīng)用程序架構(gòu)的設(shè)計思想。3.學會設(shè)計利用TCP簡單的應(yīng)用層協(xié)議。實驗內(nèi)容在Windows網(wǎng)絡(luò)環(huán)境下,以其中的2臺計算機為對象,構(gòu)成主從計算機應(yīng)用系統(tǒng),設(shè)計簡單的應(yīng)用層協(xié)議,開發(fā)基于TCP/IP的網(wǎng)絡(luò)通信程序,實現(xiàn)數(shù)據(jù)傳送等?;赥CP的計算機網(wǎng)絡(luò)通信程序,實現(xiàn)了兩人點對點聊天的功能,同時,還添加了一定的網(wǎng)絡(luò)應(yīng)用層自定義協(xié)議,例如:在聊天過程中輸入/n會在聊天對話框內(nèi)畫一個牛;輸入/p會在聊天對話框內(nèi)畫一個電話;在聊天過程中輸入/r會打開一個windows資源管理器,并打開指定的路徑;輸入/l會彈出一個對話框……;(實現(xiàn)以上功能的函數(shù)是DoAction,用的到的頭文件是有textprotcol.h)實驗步驟服務(wù)器端1:創(chuàng)建套接字并將套接字綁定到一個本地地址和端口上(create)。2:將套接字設(shè)為監(jiān)聽模式,準備接受客戶請求(listen)。3:等待客戶請求到來;請求到來后,接受請求,返回一個新的對應(yīng)于此次連接的套接字(accept)。4:用返回的套接字和客戶端進行通信(send/receive)。5:返回,等待另一客戶請求。6:關(guān)閉套接字??蛻舳?:創(chuàng)建套接字(create)。2:向服務(wù)器發(fā)出連接請求(connect)。3:和服務(wù)器進行通信(send/receive)。4:關(guān)閉套接字。(二)基于UDP/IP的計算機網(wǎng)絡(luò)通信應(yīng)用程序設(shè)計實驗?zāi)康?.通過本實驗課程的學習,使學生能夠理解UDP協(xié)議通信的基本原理。2.通過運用WinSock接口編寫網(wǎng)絡(luò)通信應(yīng)用程序,掌握UDP網(wǎng)絡(luò)應(yīng)用程序架構(gòu)的設(shè)計思想。3.學會設(shè)計利用UDP簡單的應(yīng)用層協(xié)議。實驗內(nèi)容在Windows網(wǎng)絡(luò)環(huán)境下,以其中的2臺計算機為對象,構(gòu)成主從計算機應(yīng)用系統(tǒng),設(shè)計簡單的應(yīng)用層協(xié)議,開發(fā)基于UDP/IP的網(wǎng)絡(luò)通信程序,實現(xiàn)數(shù)據(jù)傳送等?;赨DP的計算機網(wǎng)絡(luò)通信程序,實現(xiàn)了多人的點對點聊天功能,同時,還添加了一定的網(wǎng)絡(luò)應(yīng)用層自定義協(xié)議,例如:在聊天過程中輸入/n會在聊天對話框內(nèi)畫一個牛;輸入/p會在聊天對話框內(nèi)畫一個電話;在聊天中輸入/z會在聊天對話框內(nèi)畫一個豬的圖案;在聊天過程中輸入/r會打開一個windows資源管理器,并打開指定的路徑……(實現(xiàn)以上功能的函數(shù)是DoAction,用的到的頭文件是有textprotcol.h)本程序中的傳輸層協(xié)議使用的是UDP/IP協(xié)議,建立連接的過程和前面實驗類似。但是,UDP協(xié)議的在建立連接中不需要先監(jiān)聽(listen)網(wǎng)絡(luò),建立連接(connect,accept)等過程,只需要綁定指定的端口。(具體通信過程請參看PPT講義)另外,在該程序?qū)崿F(xiàn)的過程中使用了多線程。實驗步驟服務(wù)器端1.創(chuàng)建套接字并將套接字綁定到一個本地地址和端口上(create)。2.等待接收數(shù)據(jù)(ReceiveFrom)。3.關(guān)閉套接字??蛻舳?.創(chuàng)建套接字(create)。2.向服務(wù)器發(fā)送數(shù)據(jù)(sendto)。3.關(guān)閉套接字。思考題或討論題1、結(jié)合所學知識與實驗中的感受,說明TCP協(xié)議和UDP協(xié)議各自的優(yōu)缺點。在工業(yè)控制的現(xiàn)場中,要通過網(wǎng)絡(luò)控制一臺焊接機器人的運行,要求控制數(shù)據(jù)能正確傳輸。試分析說明,采用哪種運輸層協(xié)議比較好?另外,網(wǎng)絡(luò)中使用的IP電話服務(wù)采用的是哪種運輸層協(xié)議?為什么要采用這種協(xié)議?并說明理由。2、思考和調(diào)研目前常用的通信工具之一:QQ的基本實現(xiàn)方式??紤]其各種不同的應(yīng)用可能采取的是TCP和UDP中的哪種協(xié)議。如果需要對本實驗結(jié)果進行進一步改進,有哪些想法。
附錄:實驗中需要用到的WINSOCKAPI函數(shù)和數(shù)據(jù)結(jié)構(gòu)需要包含頭文件#include<winsock.h>accept():在一個套接口接受一個連接。語法:SOCKETPASCALFARaccept(SOCKETs,structsockaddrFAR*addr,intFAR*addrlen);參數(shù):s:套接口描述字,該套接口在listen()后監(jiān)聽連接。addr:(可選)指針,指向一緩沖區(qū),其中接收為通訊層所知的連接實體的地址。Addr參數(shù)的實際格式由套接口創(chuàng)建時所產(chǎn)生的地址族確定。addrlen:(可選)指針,指向存有addr地址長度的整形數(shù)。注釋:本函數(shù)從s的等待連接隊列中抽取第一個連接,創(chuàng)建一個與s同類的新的套接口并返回句柄。如果隊列中無等待連接,且套接口為非阻塞方式,則accept()阻塞調(diào)用進程直至新的連接出現(xiàn)。如果套接口為非阻塞方式且隊列中等待連接,則accept()返回一錯誤代碼。已接受連接的套接口不能用于接受新的連接,原套接口仍保持開放。addr參數(shù)為一個返回參數(shù),其中填寫的是為通訊層所知的連接實體地址。addr參數(shù)的實際格式由通訊時產(chǎn)生的地址族確定。addrlen參數(shù)也是一個返回參數(shù),在調(diào)用時初始化為addr所指的地址空間;在調(diào)用結(jié)束時它包含了實際返回的地址的長度(用字節(jié)數(shù)表示)。該函數(shù)與SOCK_STREAM類型的面向連接的套接口一起使用。如果addr與addrlen中有一個為零NULL,將不返回所接受的套接口遠程地址的任何信息。返回值:如果沒有錯誤產(chǎn)生,則accept()返回一個描述所接受包的SOCKET類型的值。否則的話,返回INVALID_SOCKET錯誤,應(yīng)用程序可通過調(diào)用WSAGetLastError()來獲得特定的錯誤代碼。addrlen所指的整形數(shù)初始時包含addr所指地址空間的大小,在返回時它包含實際返回地址的字節(jié)長度。錯誤代碼:WSANOTINITIALISED:在使用此API之前應(yīng)首先成功地調(diào)用WSAStartup()。WSAENETDOWN:WINDOWS套接口實現(xiàn)檢測到網(wǎng)絡(luò)子系統(tǒng)失效。WSAEFAULT:addrlen參數(shù)太?。ㄐ∮趕ocket結(jié)構(gòu)的大?。SAEINTR:通過一個WSACancelBlockingCall()來取消一個(阻塞的)調(diào)用。WSAEINPROGRESS:一個阻塞的WINDOWS套接口調(diào)用正在運行中。WSAEINVAL:在accept()前未激活listen()。WSAEMFILE:調(diào)用accept()時隊列為空,無可用的描述字。WSAENOBUFS:無可用緩沖區(qū)空間。WSAENOTSOCK:描述字不是一個套接口。WSAEOPNOTSUPP:該套接口類型不支持面向連接服務(wù)。WSAEWOULDBLOCK:該套接口為非阻塞方式且無連接可供接受。bind()將一本地地址與一套接口捆綁。語法:intPASCALFARbind(SOCKETs,conststructsockaddrFAR*name,intnamelen);參數(shù):s:標識一未捆綁套接口的描述字。name:賦予套接口的地址。sockaddr結(jié)構(gòu)定義如下:structsockaddr{u_shortsa_family;charsa_data[14];};namelen:name名字的長度。注釋:本函數(shù)適用于未連接的數(shù)據(jù)報或流類套接口,在connect()或listen()調(diào)用前使用。當用socket()創(chuàng)建套接口后,它便存在于一個名字空間(地址族)中,但并未賦名。bind()函數(shù)通過給一個未命名套接口分配一個本地名字來為套接口建立本地捆綁(主機地址/斷口號)。在Internet地址族中,一個名字包括幾個組成部分,對于SOCK_PGRAM和SOCK_STREAM類套接口,名字由三部分組成:主機地址,協(xié)議號(顯式設(shè)置為UDP和TCP)和用以區(qū)分應(yīng)用的端口號。如果一個應(yīng)用并不關(guān)心分配給它的地址,則可將Internet地址設(shè)置為INADDR_ANY,或?qū)⒍丝谔栔脼?。如果Internet地址段為INADDR_ANY,則可使用任意網(wǎng)絡(luò)接口;在有多種主機環(huán)境下可簡化編程。如果端口號置為0,則WINDOWS套接口實現(xiàn)將給應(yīng)用程序分配一個值在1024到5000之間的唯一的端口。應(yīng)用程序可在bind()后用getsockname()來獲知所分配的地址,但必需注意的是,getsockname()只有在套接口連接成功后才會填寫Internet地址,這是由于在多種主機環(huán)境下若干種Internet地址都是有效的。返回值:如無錯誤發(fā)生,則bind()返回0。否則的話,將返回SOCKET_ERROR,應(yīng)用程序可通過WSAGetLastError()獲取相應(yīng)錯誤代碼。錯誤代碼:WSANOTINITIALISED:在使用此API之前應(yīng)首先成功地調(diào)用WSAStartup()。WSAENETDOWN:WINDOWS套接口實現(xiàn)檢測到網(wǎng)絡(luò)子系統(tǒng)失效。WSAEADDRINUSE:所定端口已在使用中(參見setoption()中的SO_REUSEADDR選項)。WSAEFAULT:namelen參數(shù)太?。ㄐ∮趕ockaddr結(jié)構(gòu)的大?。?。WSAEINPROGRESS:一個阻塞的WINDOWS套接口調(diào)用正在運行中。WSAEAFNOSUPPORT:本協(xié)議不支持所指定的地址族。WSAEINVAL:該套接口已與一個地址捆綁。WSAENOBUFS:無足夠可用緩沖區(qū),連接過多。WSAENOTSOCK:描述字不是一個套接口。closesocket():關(guān)閉一個套接口。語法:intPASCALFARclosesocket(SOCKETs);參數(shù):s:一個套接口的描述字。注釋:本函數(shù)關(guān)閉一個套接口。更確切地說,它釋放套接口描述字s,以后對s的訪問均以WSAENOTSOCK錯誤返回。若本次為對套接口的最后一次訪問,則相應(yīng)的名字信息及數(shù)據(jù)隊列都將被釋放。closesocket()的語義受SO_LINGER與SO_DONTLINGER選項影響,對比如下:選項間隔關(guān)閉方式等待關(guān)閉與否SO_DONTLINGER不關(guān)心優(yōu)雅否SO_LINGER零強制否SO_LINGER非零優(yōu)雅是若設(shè)置了SO_LINGER,并設(shè)置了零超時間隔,則closesocket()不被阻塞立即執(zhí)行,不論是否有排隊數(shù)據(jù)未發(fā)送或未被確認。這種關(guān)閉方式稱為“強制”或“失效”關(guān)閉,因為套接口的虛電路立即被復位,且丟失了未發(fā)送的數(shù)據(jù)。在遠端的recv()調(diào)用將以WSAECONNRESET出錯。若設(shè)置了SO_LINGER并確定了非零的超時間隔,則closesocket()調(diào)用阻塞進程,直到所剩數(shù)據(jù)發(fā)送完畢或超時。這種關(guān)閉稱為“優(yōu)雅的”關(guān)閉。請注意如果套接口置為非阻塞且SO_LINGER設(shè)為非零超時,則closesocket()調(diào)用將以WSAEWOULDBLOCK錯誤返回。若在一個流類套接口上設(shè)置了SO_DONTLINGER,則closesocket()調(diào)用立即返回。但是,如果可能,排隊的數(shù)據(jù)將在套接口關(guān)閉前發(fā)送。請注意,在這種情況下WINDOWS套接口實現(xiàn)將在一段不確定的時間內(nèi)保留套接口以及其他資源,這對于想用所以套接口的應(yīng)用程序來說有一定影響。返回值:如無錯誤發(fā)生,則closesocket()返回0。否則的話,返回SOCKET_ERROR錯誤,應(yīng)用程序可通過WSAGetLastError()獲取相應(yīng)錯誤代碼。錯誤代碼:WSANOTINITIALISED:在使用此API之前應(yīng)首先成功地調(diào)用WSAStartup()。WSAENETDOWN:WINDOWS套接口實現(xiàn)檢測到網(wǎng)絡(luò)子系統(tǒng)失效。WSAENOTSOCK:描述字不是一個套接口。WSAEINPROGRESS:一個阻塞的WINDOWS套接口調(diào)用正在運行中。WSAEINTR:通過一個WSACancelBlockingCall()來取消一個(阻塞的)調(diào)用。WSAEWOULDBLOCK:該套接口設(shè)置為非阻塞方式且SO_LINGER設(shè)置為非零超時間隔。connect():建立與一個端的連接。語法:intPASCALFARconnect(SOCKETs,conststructsockaddrFAR*name,intnamelen);參數(shù):s:標識一個未連接套接口的描述字。name:欲進行連接的端口名。namelen:名字長度。注釋:本函數(shù)用于創(chuàng)建與指定外部端口的連接。s參數(shù)指定一個未連接的數(shù)據(jù)報或流類套接口。如套接口未被捆綁,則系統(tǒng)賦給本地關(guān)聯(lián)一個唯一的值,且設(shè)置套接口為已捆綁。請注意若名字結(jié)構(gòu)中的地址域為全零的話,則connect()將返回WSAEADDRNOTAVAIL錯誤。對于流類套接口(SOCK_STREAM類型),利用名字來與一個遠程主機建立連接,一旦套接口調(diào)用成功返回,它就能收發(fā)數(shù)據(jù)了。對于數(shù)據(jù)報類套接口(SOCK_DGRAM類型),則設(shè)置成一個缺省的目的地址,并用它來進行后續(xù)的send()與recv()調(diào)用。返回值:若無錯誤發(fā)生,則connect()返回0。否則的話,返回SOCKET_ERROR錯誤,應(yīng)用程序可通過WSAGetLastError()獲取相應(yīng)錯誤代碼。對阻塞套接口而言,若返回值為SOCKET_ERROR則應(yīng)用程序調(diào)用WSAGetLsatError()。如果它指出錯誤代碼為WSAEWOULDBLOCK,則您的應(yīng)用程序可以:1.用select(),通過檢查套接口是否可寫,來確定連接請求是否完成?;蛘?,2.如果您的應(yīng)用程序使用基于消息的WSAAsynSelect()來表示對連接事件的興趣,則當連接操作完成后,您會收到一個FD_CONNECT消息。錯誤代碼:WSAENOTINITIALISED:在使用此API之前應(yīng)首先成功地調(diào)用WSAStartup()。WSAENETDOWN:WINDOWS套接口實現(xiàn)檢測到網(wǎng)絡(luò)子系統(tǒng)失效。WSAEADDRINUSE:所指的地址已在使用中。WSAEINTR:通過一個WSACancelBlockingCall()來取消一個(阻塞的)調(diào)用。WSAEINPROGRESS:一個阻塞的WINDOWS套接口調(diào)用正在運行中。WSAEADDRNOTAVAIL:在本地機器上找不到所指的地址。WSAENOTSUPPORT:所指族中地址無法與本套接口一起使用。WSAECONNREFUSED:連接嘗試被強制拒絕。WSAEDESTADDREQ:需要目的地址。WSAEFAULT:namelen參數(shù)不正確。WSAEINVAL:套接口沒有準備好與一地址捆綁。WSAEISCONN:套接口早已連接。WSAEMFILE:無多余文件描述字。WSAENETUNREACH:當前無法從本主機訪問網(wǎng)絡(luò)。WSAENOBUFS:無可用緩沖區(qū)。套接口未被連接。WSAENOTSOCK:描述字不是一個套接口。WSAETIMEOUT:超時時間到。listen():創(chuàng)建一個套接口并監(jiān)聽申請的連接.語法:intPASCALFARlisten(SOCKETs,intbacklog);參數(shù):S:用于標識一個已捆綁未連接套接口的描述字。backlog:等待連接隊列的最大長度。注釋:為了接受連接,先用socket()創(chuàng)建一個套接口,然后用listen()為申請進入的連接建立一個后備日志,然后便可用accept()接受連接了。listen()僅適用于支持連接的套接口,如SOCK_STREAM類型的。套接口s處于一種“變動”模式,申請進入的連接請求被確認,并排隊等待被接受。這個函數(shù)特別適用于同時有多個連接請求的服務(wù)器;如果當一個連接請求到來時,隊列已滿,那么客戶將收到一個WSAECONNREFUSED錯誤。當沒有可用的描述字時,listen()函數(shù)仍試圖正常地工作。它仍接受請求直至隊列變空。當有可用描述字時,后續(xù)的一次listen()或accept()調(diào)用會將隊列按照當前或最近的“后備日志”重新填充,如有可能的話,將恢復監(jiān)聽申請進入的連接請求。返回值:如無錯誤發(fā)生,listen()返回0。否則的話,返回SOCKET_ERROR錯誤,應(yīng)用程序可通過WSAGetLastError()獲取相應(yīng)錯誤代碼。錯誤代碼:WSANOTINITIALISED:在使用此API之前應(yīng)首先成功地調(diào)用WSAStartup()。WSAENETDOWN:WINDOWS套接口實現(xiàn)檢測到網(wǎng)絡(luò)子系統(tǒng)失效。WSAEADDRINUSE:試圖用listen()去監(jiān)聽一個正在使用中的地址。WSAEINPROGRESS:一個阻塞的WINDOWS套接口調(diào)用正在運行中。WSAEINVAL:該套接口未用bind()進行捆綁,或已被連接。WSAEISCONN:套接口已被連接。WSAEMFILE:無可用文件描述字。WSAENOBUFS:無可用緩沖區(qū)空間。WSAENOTSOCK:描述字不是一個套接口。WSAEOPNOTSUPP:該套接口不正常listen()調(diào)用。socket():建立Socket,此函數(shù)用來建立一個Socket描述字,并為此Socket建立其所使用的資源。語法:SOCKETPASCALFARsocket(intaf,inttype,intprotocol)參數(shù):af:目前只提供PF_INET(AF_INET);type:Socket的類型(SOCK_STREAM、SOCK_DGRAM);protocol:通訊協(xié)定(如果使用者不指定則設(shè)為0);注釋:如果要建立的是遵從TCP/IP協(xié)議的socket,第二個參數(shù)type應(yīng)為SOCK_STREAM,如為UDP(數(shù)據(jù)報)的socket,應(yīng)為SOCK_DGRAM。recv():從一個套接口接收數(shù)據(jù)。語法:intPASCALFARrecv(SOCKETs,charFAR*buf,intlen,intflags);參數(shù):s:一個標識已連接套接口的描述字。buf:用于接收數(shù)據(jù)的緩沖區(qū)。len:緩沖區(qū)長度。flags:指定調(diào)用方式。注釋:本函數(shù)用于已連接的數(shù)據(jù)報或流式套接口s進行數(shù)據(jù)的接收。對SOCK_STREAM類型的套接口來說,本函數(shù)將返回所有可用的信息,最大可達緩沖區(qū)的大小。如果套接口被設(shè)置為線內(nèi)接收帶外數(shù)據(jù)(選項為SO_OOBINLINE),且有帶外數(shù)據(jù)未讀入,則返回帶外數(shù)據(jù)。應(yīng)用程序可通過調(diào)用ioctlsocket()的SOCATMARK命令來確定是否有帶外數(shù)據(jù)待讀入。對于數(shù)據(jù)報類套接口,隊列中第一個數(shù)據(jù)報中的數(shù)據(jù)被解包,但最多不超過緩沖區(qū)的大小。如果數(shù)據(jù)報大于緩沖區(qū),那么緩沖區(qū)中只有數(shù)據(jù)報的前面部分,其他的數(shù)據(jù)都丟失了,并且recv()函數(shù)返回WSAEMSGSIZE錯誤。如果沒有數(shù)據(jù)待讀,那么除非是非阻塞模式,不然的話套接口將一直等待數(shù)據(jù)的到來,此時將返回SOCKET_ERROR錯誤,錯誤代碼是WSAEWOULDBLOCK。用select()或WSAAsynSelect()可以獲知何時數(shù)據(jù)到達。如果套接口為SOCK_STREAM類型,并且遠端“優(yōu)雅”地中止了連接,那么recv()一個數(shù)據(jù)也不讀取,立即返回。如果立即被強制中止,那么recv()將以WSAECONNRESET錯誤失敗返回。在套接口的所設(shè)選項之上,還可用標志位flag來影響函數(shù)的執(zhí)行方式。也就是說,本函數(shù)的語義既取決于套接口選項,也取決于標志位參數(shù)。標志位可取下列值:MSG_PEEK查看當前數(shù)據(jù)。數(shù)據(jù)將被復制到緩沖區(qū)中,但并不從輸入隊列中刪除。MSG_OOB處理帶外數(shù)據(jù)(參見2.2.3節(jié)具體討論)。返回值:若無錯誤發(fā)生,recv()返回讀入的字節(jié)數(shù)。如果連接已中止,返回0。否則的話,返回SOCKET_ERROR錯誤,應(yīng)用程序可通過WSAGetLastError()獲取相應(yīng)錯誤代碼。錯誤代碼:WSANOTINITIALISED:在使用此API之前應(yīng)首先成功地調(diào)用WSAStartup()。WSAENETDOWN:WINDOWS套接口實現(xiàn)檢測到網(wǎng)絡(luò)子系統(tǒng)失效。WSAENOTCONN:套接口未連接。WSAEINTR:阻塞進程被WSACancelBlockingCall()取消。WSAEINPROGRESS:一個阻塞的WINDOWS套接口調(diào)用正在運行中。WSAENOTSOCK:描述字不是一個套接口。WSAEOPNOTSUPP:指定了MSG_OOB,但套接口不是SOCK_STREAM類型的WSAESHUTDOWN:套接口已被關(guān)閉。當一個套接口以0或2的how參數(shù)調(diào)用shutdown()關(guān)閉后,無法再用recv()接收數(shù)據(jù)。WSAEWOULDBLOCK:套接口標識為非阻塞模式,但接收操作會產(chǎn)生阻塞。WSAEMSGSIZE:數(shù)據(jù)報太大無法全部裝入緩沖區(qū),故被剪切。WSAEINVAL:套接口未用bind()進行捆綁。WSAECONNABORTED:由于超時或其他原因,虛電路失效。WSAECONNRESET:遠端強制中止了虛電路。send():向一個已連接的套接口發(fā)送數(shù)據(jù)。語法:intPASCALFARsend(SOCKETs,constcharFAR*buf,intlen,intflags);參數(shù):s:一個用于標識已連接套接口的描述字。buf:包含待發(fā)送數(shù)據(jù)的緩沖區(qū)。len:緩沖區(qū)中數(shù)據(jù)的長度。flags:調(diào)用執(zhí)行方式。注釋:send()適用于已連接的數(shù)據(jù)報或流式套接口發(fā)送數(shù)據(jù)。對于數(shù)據(jù)報類套接口,必需注意發(fā)送數(shù)據(jù)長度不應(yīng)超過通訊子網(wǎng)的IP包最大長度。IP包最大長度在WSAStartup()調(diào)用返回的WSAData的iMaxUdpDg元素中。如果數(shù)據(jù)太長無法自動通過下層協(xié)議,則返回WSAEMSGSIZE錯誤,數(shù)據(jù)不會被發(fā)送。請注意成功地完成send()調(diào)用并不意味著數(shù)據(jù)傳送到達。如果傳送系統(tǒng)的緩沖區(qū)空間不夠保存需傳送的數(shù)據(jù),除非套接口處于非阻塞I/O方式,否則send()將阻塞。對于非阻塞SOCK_STREAM類型的套接口,實際寫的數(shù)據(jù)數(shù)目可能在1到所需大小之間,其值取決于本地和遠端主機的緩沖區(qū)大小??捎胹elect()調(diào)用來確定何時能夠進一步發(fā)送數(shù)據(jù)。在相關(guān)套接口的選項之上,還可通過標志位flag來影響函數(shù)的執(zhí)行方式。也就是說,本函數(shù)的語義既取決于套接口的選項也取決于標志位。后者由以下一些值組成:MSG_DONTROUTE指明數(shù)據(jù)不選徑。一個WINDOWS套接口供應(yīng)商可以忽略此標志;參見2.4節(jié)中關(guān)于SO_DONTROUTE的討論。MSG_OOB發(fā)送帶外數(shù)據(jù)(僅適用于SO_STREAM;參見2.2.3節(jié))。返回值:若無錯誤發(fā)生,send()返回所發(fā)送數(shù)據(jù)的總數(shù)(請注意這個數(shù)字可能小于len中所規(guī)定的大?。7駝t的話,返回SOCKET_ERROR錯誤,應(yīng)用程序可通過WSAGetLastError()獲取相應(yīng)錯誤代碼。錯誤代碼:WSANOTINITIALISED:在使用此API之前應(yīng)首先成功地調(diào)用WSAStartup()。WSAENETDOWN:WINDOWS套接口實現(xiàn)檢測到網(wǎng)絡(luò)子系統(tǒng)失效。WSAEACESS:要求地址為廣播地址,但相關(guān)標志未能正確設(shè)置。WSAEINTR:通過一個WSACancelBlockingCall()來取消一個(阻塞的)調(diào)用。WSAEINPROGRESS:一個阻塞的WINDOWS套接口調(diào)用正在運行中。WSAEFAULT:buf參數(shù)不在用戶地址空間中的有效位置。WSAENETRESET:由于WINDOWS套接口實現(xiàn)放棄了連接,故該連接必需被復位。WSAENOBUFS:WINDOWS套接口實現(xiàn)報告一個緩沖區(qū)死鎖。WSAENOTCONN:套接口未被連接。WSAENOTSOCK:描述字不是一個套接口。WSAEOPNOTSUPP:已設(shè)置了MSG_OOB,但套接口非SOCK_STREAM類型。WSAESHUTDOWN:套接口已被關(guān)閉。一個套接口以1或2的how參數(shù)調(diào)用shutdown()關(guān)閉后,無法再用sned()函數(shù)。WSAEWOULDBLOCK:WSAEMSGSIZE:套接口為SOCK_DGRAM類型,且數(shù)據(jù)報大于WINDOWS套接口實現(xiàn)所支持的最大值。WSAEINVAL:套接口未用bind()捆綁。WSAECONNABORTED:由于超時或其他原因引起虛電路的中斷。WSAECONNRESET:虛電路被遠端復位。WSAAsyncSelect():通知套接口有請求事件發(fā)生.語法:intPASCALFARWSAAsyncSelect(SOCKETs,HWNDhWnd,unsignedintwMsg,longlEvent);參數(shù):s標識一個需要事件通知的套接口的描述符.hWnd標識一個在網(wǎng)絡(luò)事件發(fā)生時需要接收消息的窗口句柄.wMsg在網(wǎng)絡(luò)事件發(fā)生時要接收的消息.lEvent位屏蔽碼,用于指明應(yīng)用程序感興趣的網(wǎng)絡(luò)事件集合.注釋:本函數(shù)用來請求WindowsSocketsDLL為窗口句柄發(fā)一條消息-無論它何時檢測到由lEvent參數(shù)指明的網(wǎng)絡(luò)事件.要發(fā)送的消息由wMsg參數(shù)標明.被通知的套接口由s標識.本函數(shù)自動將套接口設(shè)置為非阻塞模式.lEvent參數(shù)由下表中列出的值組成.值意義FD_READ欲接收讀準備好的通知.FD_WRITE欲接收寫準備好的通知.FD_OOB欲接收帶邊數(shù)據(jù)到達的通知.FD_ACCEPT欲接收將要連接的通知.FD_CONNECT欲接收已連接好的通知.FD_CLOSE欲接收套接口關(guān)閉的通知.啟動一個WSAAsyncSelect()將使為同一個套接口啟動的所有先前的WSAAsyncSelect()作廢.例如,要接收讀寫通知,應(yīng)用程序必須同時用FD_READ和FD_WRITE調(diào)用WSAAsyncSelect(),如下:rc=WSAAsyncSelect(s,hWnd,wMsg,FD_READ|FD_WRITE);對不同的事件區(qū)分不同的消息是不可能的.下面的代碼將不會工作;第二個調(diào)用將會使第一次調(diào)用的作用失效,只有FD_WRITE會通過wMsg2消息通知到.rc=WSAAsyncSelect(s,hWnd,wMsg1,FD_READ);rc=WSAAsyncSelect(s,hWnd,wMsg2,FD_WRITE);如果要取消所有的通知,也就是指出WindowsSockets的實現(xiàn)不再在套接口上發(fā)送任何和網(wǎng)絡(luò)事件相關(guān)的消息,則lEvent應(yīng)置為0.rc=WSAAsyncSelect(s,hWnd,0,0);盡管在本例中,WSAAsyncSelect()立即使傳給該套接口的事件消息無效,仍有可能有消息等在應(yīng)用程序的消息隊列中.應(yīng)用程序因此也必須仍準備好接收網(wǎng)絡(luò)消息-即使消息作廢.用closesocket()關(guān)閉一個套接口也同樣使WSAAsyncSelect()發(fā)送的消息作廢,但在closesocke()之前隊列中的消息仍然起作用.由于一個已調(diào)用accept()的套接口和用來接收它的偵聽套接口有同樣的屬性,任何為偵聽套接口設(shè)置的的WSAAsyncSelect()事件也同樣對已接收的套接口起作用.例如,如果一個偵聽的套接口有WSAAsyncSelect()事件FD_ACCEPT,FD_READ,FD_WRITE,則任何在那個偵聽的套接口上接收的套接口將也有FD_ACCEPT,FD_READ,FD_WRITE事件,以及同樣的wMsg的值.若需要不同的wMsg及事件,應(yīng)用程序應(yīng)調(diào)用WSAAsyncSelect(),將已接收的套接口和想要發(fā)送的新消息作為參數(shù)傳遞.當某一套接口s上發(fā)生了一個已命名的網(wǎng)絡(luò)事件,應(yīng)用程序窗口hWnd會接收到消息wMsg.wParam參數(shù)標識了網(wǎng)絡(luò)事件發(fā)生的套接口.lParam的低字指明了發(fā)生的網(wǎng)絡(luò)事件.lParam的高字則含有一個錯誤代碼.該錯誤代碼可以是winsock.h中定義的任何錯誤.錯誤代碼和事件可以通過WSAGETSELECTERRORH和WSAGETSELECTEVENT宏從lParam中取出.定義如下:#defineWSAGETSELECTERROR(lParam)HIWORD(lParam)#defineWSAGETSELECTEVENT(lParam)LOWORD(lParam)注意:在accept()調(diào)用和為改變事件或wMsg的WSAAsyncSelect()調(diào)用中有一個計時窗口.應(yīng)用程序如果需要給偵聽的和調(diào)用過accept()的套接口以不同的wMsg,它就應(yīng)該在偵聽的套接口上請求FD_ACCEPT事件,然后在accept()調(diào)用后設(shè)置相應(yīng)的事件.由于FD_ACCEPT從不發(fā)送給已連接的套接口,而FD_READ,FD_WRITE,FD_OOB及FD_CLOSE也從不發(fā)送給偵聽套接口,所以不會產(chǎn)生困難.使用以上的宏將最大限度的提高應(yīng)用程序的可移植性.返回的可能網(wǎng)絡(luò)事件如下:值意義FD_READ套接口s準備讀FD_WRITE套接口s準備寫FD_OOB帶外數(shù)據(jù)準備好在套接口s上讀.FD_ACCEPT套接口s準備接收新的將要到來的連接.FD_CONNECT套接口s上的連接完成.FD_CLOSE由套接口s標識的連接已關(guān)閉.返回值:0若應(yīng)用程序感興趣的網(wǎng)絡(luò)事件的聲明成功.SOCKET_ERROR否則.可通過調(diào)用WSAGetLastError()返回特定的錯誤代碼.錯誤代碼:WSANOTINITIALISED在使用本API前必須進行一次成功的WSAStartup()調(diào)用.WSAENETDOWNWINDOWSSOCKETS實現(xiàn)已檢測到網(wǎng)絡(luò)子系統(tǒng)故障.WSAEINVAL指出指定的參數(shù)之一是非法的.WSAEINPROGRESS一個阻塞的WindowsSockets操作正在進行.附加的錯誤代碼可能在應(yīng)用程序窗口接收到消息時被置.這些代碼可以用WSAGETSELECTERROR宏從lParam中取出.對應(yīng)于每個網(wǎng)絡(luò)事件的可能錯誤代碼為:事件:FD_CONNECTWSAEADDRINUSE給定的地址已被使用.WSAEADDRNOTAVAIL指定的地址在本地機器不能使用.WSAEAFNOSUPPORT指定族的地址不能和本套接口同時使用.WSAECONNREFUSED連接的
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 鋼鐵行業(yè)保安工作總結(jié)
- 點滴關(guān)懷感染科護士總結(jié)
- 科技在前臺工作中的應(yīng)用計劃
- 網(wǎng)絡(luò)科技行業(yè)客服工作總結(jié)
- 2024年稅務(wù)師題庫帶答案(典型題)
- 2024年設(shè)備監(jiān)理師考試題庫及答案4
- 2024年認識冰的教案
- 2024年燃氣管網(wǎng)工安全作業(yè)技能考試題庫及答案
- 2024年花兒朵朵教案
- 2024年電工安全總結(jié)
- 2024年山東魯商集團有限公司招聘筆試參考題庫含答案解析
- 妊娠劇吐伴酮癥護理查房課件
- 200#溶劑油安全技術(shù)說明書
- 單位洗車房管理制度
- 廣西壯族自治區(qū)欽州市浦北縣2022-2023學年七年級上學期期末英語試題
- 動力學全套課件
- 廣東省深圳市2022-2023學年六年級上學期語文期末試卷(含答案)6
- 2022-2023學年北京市海淀區(qū)高一(上)期末生物試卷(附答案詳解)
- 河南省出版物經(jīng)營許可證申請登記表
- 細集料篩分試驗檢測記錄表模板
- (完整word版)聘書模板紅色
評論
0/150
提交評論