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