



版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、第14章 SOCKET類的設計和實現14.1 WinSock基本知識這里不打算系統地介紹socket 或者 WinSock塞/ 非阻塞的概念;然后介紹socket 的使用。的知識。首先介紹WinSockAPI 函數,講解阻WinSock APISocket 接口是網絡編程(通常是TCP/IP 協議,也可以是其他協議)的API 。最早的Socket接口是 Berkeley 接口,在 Unxi 操作系統中實現。 WinSock 也是一個基于Socket 模型的 API ,在 Microsoft Windows操作系統類中使用。它在Berkeley 接口函數的基礎之上,還增加了基于消息驅動機制的Wi
2、ndows 擴展函數。 Winscok1.1 只支持 TCP/IP 網絡, WinSock2.0 增加了對更多協議的支持。這里,討論TCP/IP 網絡上的API 。Socket 接口包括三類函數:第一類是 WinSock API 包含的 Berkeley socket 函數。這類函數分兩部分。第一部分是用于網絡 I/O 的函數,如accept、 Closesocket、connect、 recv、 recvfrom 、Select、 Send、Sendto另一部分是不涉及網絡 I/O 、在本地端完成的函數,如bind 、getpeername、 getsockname、 getsocketop
3、t、 htonl、 htons、 inet_addr、 inet_nton ioctlsocket 、 listen 、ntohl 、 ntohs、 setsocketopt、 shutdow 、socket 等第二類是檢索有關域名、通信服務和協議等Internet 信息的數據庫函數,如gethostbyaddr、gethostbyname、 gethostname、 getprotolbyname getprotolbynumber 、 getserverbyname、 getservbyport 。第三類是 Berkekley socket 例程的Windows 專用的擴展函數,如geth
4、ostbyname 對應的WSAAsynGetHostByName (其他數據庫函數除了gethostname 都有異步版本) ,select 對應的WSAAsynSelect ,判斷是否阻塞的函數WSAIsBlocking ,得到上一次 Windsock API 錯誤信息的 WSAGetLastError ,等等。從另外一個角度,這些函數又可以分為兩類,一是阻塞函數, 一是非阻塞函數。所謂阻塞函數,是指其完成指定的任務之前不允許程序調用另一個函數,在Windows 下還會阻塞本線程消息的發送。所謂非阻塞函數,是指操作啟動之后,如果可以立即得到結果就返回結果,否則返回表示結果需要等待的錯誤信息
5、,不等待任務完成函數就返回。首先,異步函數是非阻塞函數;其次,獲取遠地信息的數據庫函數是阻塞函數(因此,WinSock 提供了其異步版本) ;在 Berkeley socket 函數部分中,不涉及網絡I/O 、本地端工作的函數是非阻塞函數;在 Berkeley socket 函數部分中,網絡I/O的函數是可阻塞函數,也就是它們可以阻塞執行,也可以不阻塞執行。這些函數都使用了一個socket,如果它們使用的 socket 是阻塞的,則這些函數是阻塞函數;如果它們使用的socket 是非阻塞的,則這些函數是非阻塞函數。創建一個 socket 時,可以指定它是否阻塞。 在缺省情況下, Berkerl
6、ey 的 Socket 函數和 WinSock 都創建 “阻塞” 的 socket。阻塞 socket 通過使用 select 函數或者 WSAAsynSelect 函數在指定操作下變成非阻塞的。WSAAsyncSelect 函數原型如下。int WSAAsyncSelect(SOCKET s,HWND hWnd,u_int wMsg,long lEvent);其中,參數 1 個消息,參數指定了要操作的 socket 句柄;參數 2 指定了一個窗口句柄;參數 4 指定了網絡事件,可以是多個事件的組合,如:3 指定了一FD_READ FD_WRITE FD_OOB FD_ACCEPT FD_CO
7、NNECT FD_CLOSE準備讀準備寫帶外數據到達收到連接完成連接關閉 socket。用 OR 操作組合這些事件值,如 FD_READ|FD_WRITEWSAAsyncSelect 函數表示對 socket s 監測 lEvent 指定的網絡事件,如果有事件發生,則給窗口 hWnd 發送消息 wMsg 。假定應用程序的一個 socket s 指定了監測 FD_READ 事件, 則在 FD_READ 事件上變成非阻塞的。當 read 函數被調用時,不管是否讀到數據都馬上返回,如果返回一個錯誤信息表示還在等待,則在等待的數據到達后,消息wMsg 發送給窗口hWnd ,應用程序處理該消息讀取網絡數
8、據。對于異步函數的調用,以類似的過程最終得到結果數據。以gethostbyname 的異步版本的使用為例進行說明。該函數原型如下:HANDLE WSAAsyncGetHostByName(HWND hWnd,u_int wMsg,const char FAR *name,char FAR *buf,int buflen);在調用 WSAAsyncGetHostByName啟動操作時,不僅指定主機名字name,還指定了一個窗口句柄 hWnd ,一個消息ID wMsg ,一個緩沖區及其長度。如果不能立即得到主機地址,則返回一個錯誤信息表示還在等待。當要的數據到達時,WinSockDLL 給窗口hW
9、nd 發送消息 wMsg 告知得到了主機地址,窗口過程從指定的緩沖區buf 得到主機地址。使用異步函數或者非阻塞的socket,主要是為了不阻塞本線程的執行。在多進程或者多線程的情況下,可以使用兩個線程通過同步手段來完成異步函數或者非阻塞函數的功能。Socket 的使用WinSock以DLL的形式提供,在調用任何WinSock API 之前,必須調用函數WSAStartup進行初始化,最后,調用函數WSACleanUp 作清理工作。MFC 使用函數AfxSocketInit包裝了函數WSAStartup ,在IninInstance 中調用 AfxSocketInit進行初始化。程序不必調用W
10、inSock 應用程序的初始化函數WSACleanUp 。Socket 是網絡通信過程中端點的抽象表示。Socket 在實現中以句柄的形式被創建,包含了進行網絡通信必須的五種信息:連接使用的協議,本地主機的IP 地址,本地進程的協議端口,遠地主機的IP 地址,遠地進程的協議端口。要使用 socket,首先必須創建一個socket;然后,按要求配置socket;接著,按要求通過socket接收和發送數據;最后,程序關閉此socket。為了創建socket,使用 socket 函數得到一個socket 句柄:socket_handle = socket(protocol_family. Socke
11、t_type, protocol);其中:protocol_family指定 socket 使用的協議, 取值 PF_INET ,表示 Internet(TCP/IP) 協議族;Socket_type 指當一個 socket 的信息,到此,socket 面向連接或者使用數據報;第三個參數表示使用TCP 或者被創建時, WinSock 將為一個內部結構分配內存,在此結構中保存此socket 連接使用的協議已經確定。UDP協議。socket創建了 socket 之后,配置socket。對于面向連接的客戶, WinSock 自動保存本地 IP 地址和選擇協議端口, 但是必須使用 connect 函數
12、配置遠地 IP 地址和遠地協議端口:result = connect(socket_handle, remote_socket_address, address_length)remote_socket_address 是一個指向特定socket 結構的指針, 該地址結構為socket 保存了地址族、協議端口、網絡主機地址。面向連接的服務器則使用bind使用數據報的客戶或者服務器使用定遠地信息。指定本地信息,使用listen 和 accept 獲取遠地信息。bind 給 socket 指定本地信息,在發送或者接收數據時指bind 給 socket 指定一個本地IP 地址和協議端口,如下:res
13、ult = bind( socket_hndle, local_socket_address, address_length)參數類型同connect。函數 listen 監聽 bind 指定的端口, 如果有遠地客戶請求連接,個新的 socket,并保存信息。使用accept 接收請求, 創建一socket_new = accept(socket_listen, socket_address, address_length)在 socket 配置好之后,使用socket 發送或者接收數據。面向連接的socket 使用 send 發送數據, recv 接收數據;使用數據報的socket 使用 s
14、endto 發送數據, recvfrom 接收數據。14.2 MFC 對 WinSockt API的封裝MFC提供了兩個類CAsyncSocket和CSocket來封裝WinSock API,這給程序員提供了一個更簡單的網絡編程接口。CAsyncSocket 在較低層次上封裝了WinSock API ,缺省情況下, 使用該類創建的socket 是非阻塞的 socket,所有操作都會立即返回,如果沒有得到結果,返回WSAEWOULDBLOCK,表示是一個阻塞操作。CSocket 建立在 CAsyncSocket 的基礎上,是 CAsyncSocket 的派生類。也就是缺省情況下使用該類創建的 s
15、ocket 是非阻塞的 socket,但是 CSocket 的網絡 I/O 是阻塞的,它在完成任務之后才返回。 CSocket 的阻塞不是建立在“阻塞” socket 的基礎上,而是在“非阻塞” socket 上實現的阻塞操作,在阻塞期間, CSocket 實現了本線程的消息循環,因此,雖然是阻塞操作,但是并不影響消息循環,即用戶仍然可以和程序交互。CAsyncSocketCAsyncSocket 封裝了低層的WinSock API ,其成員變量m_hSocket 保存其對應的socket 句柄。使用 CAsyncSocket 的方法如下:首先,在堆或者棧中構造一個CAsyncSocket對象
16、,例如:CAsyncSocket sock ;或者CAsyncSocket *pSock = new CAsyncSocket;其次,調用Create 創建 socket,例如:使用缺省參數創建一個面向連接的socketsock.Create()指定參數參數創建一個使用數據報的socket,本地端口為30pSocket.Create(30, SOCK_DGRM) ;其三,如果是客戶程序,使用Connect 連接到遠地;如果是服務程序,使用的連接請求。其四,使用成員函數進行網絡I/O。最后,銷毀CAsyncSocket ,析構函數調用Close 成員函數關閉socket。Listen 監聽遠地下
17、面,分析CAsyncSocket 的幾個函數,從中可以看到它是如何封裝低層的簡化有關操作的;還可以看到它是如何實現非阻塞的socket 和非阻塞操作。WinSockAPI ,socket對象的創建和捆綁( 1) Create 函數首先,討論Create 函數,分析socket 句柄如何被創建并和CAsyncSocket對象關聯。 Create的實現如下:BOOL CAsyncSocket:Create(UINT nSocketPort, int nSocketType,long lEvent, LPCTSTR lpszSocketAddress)if (Socket(nSocketType,
18、lEvent)if (Bind(nSocketPort,lpszSocketAddress)return TRUE;int nResult = GetLastError();Close();WSASetLastError(nResult);return FALSE;其中:參數 1 表示本 socket 的端口,缺省是號。參數 2 表示本 socket 的類型,缺省是0,如果要創建數據報的socket,則必須指定一個端口SOCK_STREAM ,表示面向連接類型。參數 3 是屏蔽位,表示希望對本socket 監測的事件,缺省是 FD_READ | FD_WRITE | FD_OOB| FD_AC
19、CEPT | FD_CONNECT | FD_CLOSE。參數4 表示本socket的IP 地址字符串,缺省是NULL。Create 調用 Socket 函數創建一個socket,并把它捆綁在this 所指對象上, 監測指定的網絡事件。參數2和 3 被傳遞給 Socket 函數,如果希望創建數據報的socket,不要使用缺省參數,指定參數2是 SOCK_DGRM 。如果上一步驟成功,則調用bind 給新的 socket 分配端口和 IP 地址。( 2) Socket 函數接著,分析Socket 函數,其實現如下:BOOL CAsyncSocket:Socket(int nSocketType,
20、 long lEvent,int nProtocolType, int nAddressFormat)ASSERT(m_hSocket = INVALID_SOCKET);m_hSocket = socket(nAddressFormat,nSocketType,nProtocolType);if (m_hSocket != INVALID_SOCKET)CAsyncSocket:AttachHandle(m_hSocket, this, FALSE);return AsyncSelect(lEvent);return FALSE;其中:參數 1 表示 Socket 類型,缺省值是SOCK_S
21、TREAM 。參數 2 表示希望監測的網絡事件,缺省值同Create,指定了全部事件。參數 3 表示使用的協議,缺省是 0。實際上, SOCK_STREAM類型的socket 使用TCP協議,SOCK_DGRM的 socket 則使用 UDP 協議。參數 4 表示地址族 (地址格式) ,缺省值是PF_INET(等同于 AF_INET )。對于 TCP/IP 來說,協議族和地址族是同值的。在 socket 沒有被創建之前,成員變量m_hSocket 是一個無效的socket 句柄。 Socket 函數把協議族、 socket 類型、使用的協議等信息傳遞給WinSock API 函數 socket
22、,創建一個socket。如果創建成功,則把它捆綁在this 所指對象。( 3)捆綁( Attatch )捆綁過程類似于其他Windows 對象,將在模塊線程狀態的WinSock 映射中添加一對新的映射: this 所指對象和新創建的socket 對象的映射。另外,如果本模塊線程狀態的“socket 窗口”沒有創建,則創建一個,該窗口在異步操作時用來接收 WinSock 的通知消息,窗口句柄保存到模塊線程狀態的m_hSocketWindow 變量中。函數 AsyncSelect 將指定該窗口為網絡事件消息的接收窗口。函數 AttachHandle 的實現在此不列舉了。( 4)指定要監測的網絡事件
23、在捆綁完成之后,調用 AsyncSelect 指定新創建的socket 將監測的網絡事件。AsyncSelect 實現如下:BOOL CAsyncSocket:AsyncSelect(long lEvent)ASSERT(m_hSocket != INVALID_SOCKET);_AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;ASSERT(pState->m_hSocketWindow != NULL);return WSAAsyncSelect(m_hSocket, pState->m_hSocketWindow,WM_S
24、OCKET_NOTIFY, lEvent) != SOCKET_ERROR;函數參數lEvent 表示希望監視的網絡事件。_ afxSockThreadState 得到的是當前的模塊線程狀態,m_ hSocketWindow程的“socket 窗口” ,指定監視m_hSocket 的網絡事件,如指定事是本模塊在當前線件發生,給窗口m_hSocketWindow發送WM_SOCKET_NOTIFY消息。被指定的網絡事件對應的網絡I/O 將是異步操作,是非阻塞操作。例如:指定FR_READ 導致 Receive 是 一 個 異 步 操 作 , 如 果 不 能 立 即 讀 到 數 據 , 則 返 回
25、 一 個 錯 誤WSAEWOULDBLOCK。在數據到達之后,WinSock通知窗口m_hSocketWindow ,導致OnReceive被調用。指 定FR_WRITE導 致Send 是 一 個異 步 操 作 ,即 使 數 據 沒 有送 出 也 返 回 一 個 錯 誤。在數據可以發送之后, WinSock 通知窗口 m_hSocketWindow ,導致 WSAEWOULDBLOCKOnSend 被調用。指定FR_CONNECTWSAEWOULDBLOCK導致Connect 是一個異步操作,還沒有連接上就返回錯誤信息,在連接完成之后,WinSock通知窗口m_hSocketWindow,導致
26、OnConnect被調用。對于其他網絡事件,就不一一解釋了。所以,使用 CAsyncSocket 時,如果使用 Create 缺省創建 socket,則所有網絡 I/O 都是異步操作,進行有關網絡 I/O 時則必須覆蓋以下的相關函數:OnAccept 、 OnClose、 OnConnect、 OnOutOfBandData 、 OnReceive、OnSend。( 5) Bind 函數經過上述過程,socket 創建完畢,下面,調用Bind函數給m_hSocket指定本地端口和IP地址。 Bind 的實現如下:BOOL CAsyncSocket:Bind(UINT nSocketPort,
27、LPCTSTR lpszSocketAddress)USES_CONVERSION;/使用 WinSock 的地址結構構造地址信息SOCKADDR_IN sockAddr;memset(&sockAddr,0,sizeof(sockAddr);/得到地址參數的值LPSTR lpszAscii = T2A(LPTSTR)lpszSocketAddress);/指定是 Internet 地址類型sockAddr.sin_family = AF_INET;if (lpszAscii = NULL)/沒有指定地址,則自動得到一個本地IP 地址/把 32 比特的數據從主機字節序轉換成網絡字節序e
28、lse/得到地址DWORD lResult = inet_addr(lpszAscii);if (lResult = INADDR_NONE)WSASetLastError(WSAEINVAL);return FALSE;/如果端口為0,則 WinSock 分配一個端口(1024 5000)/把 16 比特的數據從主機字節序轉換成網絡字節序sockAddr.sin_port = htons(u_short)nSocketPort);/Bind 調用 WinSock API 函數 bindreturn Bind(SOCKADDR*)&sockAddr, sizeof(sockAddr);
29、其中:函數參數1 指定了端口;參數2 指定了一個包含本地地址的字符串,缺省是NULL 。函數 Bind 首先使用結構 SOCKADDR_IN 構造地址信息。 該結構的域 sin_family 表示地址格式( TCP/IP 同協議族),賦值為 AF_INET ( Internet 地址格式);域 sin_port 表示端口,如果參數 1 為 0,則 WinSock 分配一個端口給它,范圍在1024 和 5000 之間;域 sin_addr 是表示地址信息,它是一個聯合體,其中s_addr 表示如下形式的字符串,“ ”。如果參數沒有指定地址,則 WinSock 自動地得到本地 IP 地址(如果有幾
30、個網卡,則使用其中一個的地址)。( 6)總結 Create 的過程首先,調用socket 函數創建一個socket;然后把創建的socket 對象映射到CAsyncSocket 對象(捆綁在一起) ,指定本socket 要通知的網絡事件,并創建一個“socket 窗口”來接收網絡事件消息,最后,指定socket 的本地信息。下一步,是使用成員函數Connect 連接遠地主機,配置socket 的遠地信息。函數Connect 類似于 Bind ,把指定的遠地地址轉換成SOCKADDR_IN對象表示的地址信息(包括網絡字節序的轉換),然后調用WinSock 函數 Connect 連接遠地主機,配置
31、socket 的遠地端口和遠地IP 地址。異步網絡事件的處理當網絡事件發生時,“ socket 窗口”接收WM_SOCKET_NOTIFY消息,消息處理函數OnSocketNotify 被調用。“ socket 窗口”的定義和消息處理是MFC 實現的,這里不作詳細的討論。OnSocketNotify 回調 CAsyncSocket 的成員函數 DoCallBack ,DoCallBack 調用事件處理函數,如 OnRead、 OnWrite 等。摘錄 DoCallBack 的一段代碼如下:switch (WSAGETSELECTEVENT(lParam)case FD_READ:DWORD n
32、Bytes;/ 得到可以一次讀取的字節數pSocket->IOCtl(FIONREAD, &nBytes);if (nBytes != 0)pSocket->OnReceive(nErrorCode);break;case FD_WRITE:pSocket->OnSend(nErrorCode);break;case FD_OOB:pSocket->OnOutOfBandData(nErrorCode);break;case FD_ACCEPT:pSocket->OnAccept(nErrorCode);break;case FD_CONNECT:pSoc
33、ket->OnConnect(nErrorCode);break;case FD_CLOSE:pSocket->OnClose(nErrorCode);break;lParam 是 WM_SOCKET_NOFITY 的消息參數, OnSocketNotify 傳遞給函數 DoCallBack ,表示通知事件。函數 IOCtl 是 CAsyncSocket 的成員函數,用來對 socket 的 I/O 進行控制。這里的使用表示本次調用 Receive 函數至多可以讀 nBytes 個字節。從上面的討論可以看出, 從創建 socket 到網絡 I/O ,CAsyncSocket 直接封
34、裝了低層的 WinSock API ,簡化了 WinSock 編程,實現了一個異步操作的界面。如果希望某個操作是阻塞操作,則在調用Create 時不要指定該操作對應的網絡事件。例如,希望Connect 和 Send 是阻塞操作,在任務完成之后才返回,則可以使用如下的語句:pSocket->Create(0, SOCK_STREAM,FR_WRITE|FR_OOB|FR_ACCEPT|FR_CLOSE);這樣,在 Connect 和 Send 時,如果是用戶界面線程的話,可能阻塞線程消息循環。所以,最好在工作者線程中使用阻塞操作。14.3 CSocket如果希望在用戶界面線程中使用阻塞 s
35、ocket,則可以使用 CSocket。它在非阻塞 socket 基礎之上實現了阻塞操作,在阻塞期間實現了消息循環。對于 CSocket,處理網絡事件通知的函數OnAccept 、OnClose、 OnReceive 仍然可以使用,OnConnect、 OnSend 在CSocket中永遠不會被調用,另外OnOutOfBandData在CSocket中不鼓勵使用。CSocket 對象在調用Connect、Send、 Accept、Close、Receive 等成員函數后,這些函數在完成任務之后(連接被建立、數據被發送、連接請求被接收、socket 被關閉、數據被讀取)之后才會返回。因此, Co
36、nnect 和 Send 不會導致 OnConnect 和 OnSend 被調用。如果覆蓋虛擬函數 OnReceive、OnAccept 、OnClose,不主動調用 Receive、 Accept、Close,則在網絡事件到達之后導致對應的虛擬函數被調用,虛擬函數的實現應該調用 Receive、Accept 、Close 來完成操作。下面,就一個函數 Receive 來考察 CSocket 如何實現阻塞操作和消息循環的。int CSocket:Receive(void* lpBuf, int nBufLen, int nFlags)/m_pbBlocking 是 CSocket 的成員變量,
37、用來標識當前是否正在進行/阻塞操作。但不能同時進行兩個阻塞操作。if (m_pbBlocking != NULL)WSASetLastError(WSAEINPROGRESS);returnFALSE;/完成數據讀取int nResult;while (nResult = CAsyncSocket:Receive(lpBuf, nBufLen, nFlags)= SOCKET_ERROR)if (GetLastError() = WSAEWOULDBLOCK)/ 進入消息循環,等待網絡事件if (!PumpMessages(FD_READ)return SOCKET_ERROR;FD_READ
38、elsereturn SOCKET_ERROR;return nResult;其中:參數 1 指定一個緩沖區保存讀取的數據; 參數(數據拷貝到緩沖區,但不從輸入隊列移走)2 指定緩沖區的大小; 參數 3 取值 MSG_PEEK ,或者 MSG_OOB (處理帶外數據) ,或者MSG_PEEK|MSG_OOB。Receive 函數首先判斷當前 CSocket 對象是否正在處理一個阻塞操作,如果是,則返回錯誤 WSAEINPROGRESS ;否則,開始數據讀取的處理。讀取數據時,如果基類CAsyncSocket 的 Receive 讀取到了數據,則返回;否則,如果返回一個錯誤, 而且錯誤號是WSA
39、EWOULDBLOCK,則表示操作阻塞,于是調用 PumpMessage進入消息循環等待數據到達(網絡事件 FD_READ 發生)。數據到達之后退出消息循環,再次調用 CAsyncSocket 的 Receive 讀取數據,直到沒有數據可讀為止。PumpMessages 是 CSocket 的成員函數,它完成以下工作:( 1)設置 m_pbBlocking ,表示進入阻塞操作。( 2)進行消息循環,如果有以下事件發生則退出消息循環:收到指定定時器的定時事件消息 WM_TIMER , 退 出 循 環 , 返 回 TRUE ; 收 到 發 送 給 本 socket 的 消 息 WM_SOCKET_
40、NOTIFY ,網絡事件 FD_CLOSE 或者等待的網絡事件發生,退出循環,返回TRUE ;發送錯誤或者收到WM_QUIT消息,退出循環,返回FALSE ;( 3)在消息循環中,把WM_SOCKET_DEAD消息和發送給其他socket 的通知消息WM_SOCKET_NOFITY放進模塊線程狀態的通知消息列表m_listSocketNotifications ,在阻塞操作完成之后處理;對其他消息,則把它們送給目的窗口的窗口過程處理。14.4 CSocketFileMFC還提供了一個網絡編程模式,可以充分利用CSocket 的特性。該模式的基礎是CSocketFile 類。使用方法如下:首先,
41、構造一個 CSocket 對象;調用 Create 函數創建一個 socket 對象( SOCK_STREAM 類型)。接著,如果是客戶程序,調用Connect 連接到遠地主機;如果是服務器程序,先調用Listen監聽 socket 端口,收到連接請求后調用Accept 接收請求。然后, 創建一個和CSocket 對象關聯的CSocketFile 對象,創建一個和CSocketFile 對象關聯的 CArchive 對象,指定 CArchive對象是用于讀或者寫。如果既要讀又要寫,則創建兩個CArchive 對象。創建工作完成之后,使用CArchive對象在客戶和服務器之間傳送數據使用完畢,銷
42、毀 CArchive 對象、 CSocketFile 對象、 CSocket 對象。從前面的章節可以知道,CArchive可以以一個 CFile 對象為基礎,通過<<和 >>操作符完成對文件的二進制流的操作。所以可以從CFile 派生一個類,實現 CFile 的操作界面( Read 和Write )。由于 CSocket 提供了阻塞操作,所以完全可以像讀寫文件一樣讀寫socket 數據。下面,分析 CSocketFile 的設計和實現。( 1) CSocketFile 的構造函數和析構函數的實現構造函數的實現CSocketFile:CSocketFile(CSocket
43、* pSocket, BOOL bArchiveCompatible)m_pSocket = pSocket;m_bArchiveCompatible = bArchiveCompatible;#ifdef _DEBUGASSERT(m_pSocket != NULL);ASSERT(m_pSocket->m_hSocket != INVALID_SOCKET);int nType = 0;int nTypeLen = sizeof(int);ASSERT(m_pSocket->GetSockOpt(SO_TYPE,&nType,&nTypeLen);ASSERT(nType = SOCK_STREAM);#endif / _DEBUG其中:構造函數的參數 1 指向關聯的參數 2 指定該對象是否和一個CSocket CArchive對象,被保存在成員變量m_pSocket 中;對象關聯 (不關聯則獨立使用) ,被保存在成員變量bArchiveCompatibl
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025探索服務合同的試用期
- 2024年超臨界CO2萃取裝置膜生物反應器及其他項目資金申請報告代可行性研究報告
- 2025潤滑油銷售合同協議
- 2025全日制勞動合同
- 2025年國稅局合同制人員醫療險問題
- 2025勞動合同(教師)
- 2025宜昌市存量房買賣合同
- 2025《廣州市合同范本》
- 2025深圳市租賃合同協議
- 2025國內認證委托合同
- (三診)綿陽市高中2022級高三第三次診斷性考試 歷史試卷A卷(含答案)
- 麻醉專業考試試題及答案
- 2024華能四川能源開發有限公司下屬單位招聘筆試參考題庫附帶答案詳解
- 湖南省長沙市長郡教育集團2024-2025學年七年級下學期期中生物試題
- 鋼結構高處作業安全管理
- JJF 2221-2025導熱系數瞬態測定儀校準規范
- 山東省高中名校2025屆高三4月校際聯合檢測大聯考生物試題及答案
- 2025年武漢數學四調試題及答案
- 【MOOC】數學建模精講-西南交通大學 中國大學慕課MOOC答案
- 職業病防護設施與個體防護用品的使用和維護
- 2024年全國高中數學聯賽北京賽區預賽一試試題(解析版)
評論
0/150
提交評論