複製鏈接
請複製以下鏈接發送給好友

sockets

鎖定
Sockets是Windows下網絡編程的規範,Windows Sockets是Windows下得到廣泛應用的、開放的、支持多種協議的網絡編程接口。從1991年的1.0版到1995年的2.0.8版,經過不斷完善並在Intel、Microsoft、Sun、SGI、InformixNovell等公司的全力支持下,已成為Windows網絡編程的事實上的標準。
中文名
網絡編程接口
外文名
Sockets
所屬學科
計算機
接    口
Windows下支持多種協議
規    範
microsoft
關    係
通信的基礎是套接口

目錄

sockets基本介紹

WindowsSockets規範以U.C.Berkeley大學BSDUNIX中流行的Socket接口為範例定義了一套microsoftWindows下網絡編程接口。它不僅包含了人們所熟悉的BerkeleySocket風格的庫函數;也包含了一組針對Windows的擴展庫函數,以使程序員能充分地利用Windows消息驅動機制進行編程。WindowsSockets規範本意在於提供給應用程序開發者一套簡單的API,並讓各家網絡軟件供應商共同遵守。此外,在一個特定版本Windows的基礎上,WindowsSockets也定義了一個二進制接口(ABI),以此來保證應用WindowsSocketsAPI的應用程序能夠在任何網絡軟件供應商的符合WindowsSockets協議的實現上工作。因此這份規範定義了應用程序開發者能夠使用,並且網絡軟件供應商能夠實現的一套庫函數調用和相關語義。遵守這套WindowsSockets規範的網絡軟件,我們稱之為WindowsSockets兼容的,而WindowsSockets兼容實現的提供者,我們稱之為WindowsSockets提供者。一個網絡軟件供應商必須百分之百地實現WindowsSockets規範才能做到現WindowsSockets兼容。任何能夠與WindowsSockets兼容實現協同工作的應用程序就被認為是具有WindowsSockets接口。我們稱這種應用程序為WindowsSockets應用程序。WindowsSockets規範定義並記錄瞭如何使用API與Internet協議族(IPS,通常我們指的是TCP/IP)連接,尤其要指出的是所有的WindowsSockets實現都支持流套接口數據報套接口.應用程序調用WindowsSockets的API實現相互之間的通訊。WindowsSockets又利用下層的網絡通訊協議功能和操作系統調用實現實際的通訊工作。

sockets關係

通信的基礎是套接口(Socket),一個套接口是通訊的一端。在這一端上你可以找到與其對應的一個名字。一個正在被使用的套接口都有它的類型和與其相關的進程。套接口存在於通訊域中。通訊域是為了處理一般的線程通過套接口通訊而引進的一種抽象概念。套接口通常和同一個域中的套接口交換數據(數據交換也可能穿越域的界限,但這時一定要執行某種解釋程序)。WindowsSockets規範支持單一的通訊域,即Internet域。各種進程使用這個域互相之間用Internet協議族來進行通訊(WindowsSockets1.1以上的版本支持其他的域,例如WindowsSockets2)。套接口可以根據通訊性質分類;這種性質對於用户是可見的。應用程序一般僅在同一類的套接口間通訊。不過只要底層的通訊協議允許,不同類型的套接口間也照樣可以通訊。用户可以使用兩種套接口,即流套接口和數據報套接口。流套接口提供了雙向的,有序的,無重複並且無記錄邊界的數據流服務。數據報套接口支持雙向的數據流,但並不保證是可靠,有序,無重複的。也就是説,一個從數據報套接口接收信息的進程有可能發現信息重複了,或者和發出時的順序不同。數據報套接口的一個重要特點是它保留了記錄邊界。對於這一特點,數據報套接口採用了與許多包交換網絡(例如以太網)非常類似的模型。
一個在建立分佈式應用時最常用的範例便是客户機/服務器模型。在這種方案中客户應用程序向服務器程序請求服務。這種方式隱含了在建立客户機/服務器間通訊時的非對稱性。客户機/服務器模型工作時要求有一套為客户機和服務器所共識的慣例來保證服務能夠被提供(或被接受)。這一套慣例包含了一套協議。它必須在通訊的兩頭都被實現。根據不同的實際情況,協議可能是對稱的或是非對稱的。在對稱的協議中,每一方都有可能扮演主從角色;在非對稱協議中,一方被不可改變地認為是主機,而另一方則是從機。一個對稱協議的例子是Internet中用於終端仿真TELNET。而非對稱協議的例子是Internet中的FTP。無論具體的協議是對稱的或是非對稱的,當服務被提供時必然存在"客户進程"和"服務進程"。一個服務程序通常在一個眾所周知的地址監聽對服務的請求,也就是説,服務進程一直處於休眠狀態,直到一個客户對這個服務的地址提出了連接請求。在這個時刻,服務程序被"驚醒"並且為客户提供服務-對客户的請求作出適當的反應。這一請求/相應的過程可以簡單的用圖表示。雖然基於連接的服務是設計客户機/服務器應用程序時的標準,但有些服務也是可以通過數據報套接口提供的。
sockets sockets
數據報套接口可以用來向許多系統支持的網絡發送廣播數據包。要實現這種功能,網絡本身必須支持廣播功能,因為系統軟件並不提供對廣播功能的任何模擬。廣播信息將會給網絡造成極重的負擔,因為它們要求網絡上的每台主機都為它們服務,所以發送廣播數據包的能力被限制於那些用顯式標記了允許廣播的套接口中。廣播通常是為了如下兩個原因而使用的:1.一個應用程序希望在本地網絡中找到一個資源,而應用程序對該資源的地址又沒有任何先驗的知識。2.一些重要的功能,例如路由要求把它們的信息發送給所有可以找到的鄰機。被廣播信息的目的地址取決於這一信息將在何種網絡上廣播。Internet域中支持一個速記地址用於廣播-INADDR_BROADCAST。由於使用廣播以前必須捆綁一個數據報套接口,所以所有收到的廣播消息都帶有發送者的地址和端口。
Intel處理器字節順序是和DECVAX處理器的字節順序一致的。因此它與68000型處理器以及Internet的順序是不同的,所以用户在使用時要特別小心以保證正確的順序。任何從WindowsSockets函數對IP地址端口號的引用和傳送給WindowsSockets函數的IP地址和端口號均是按照網絡順序組織的,這也包括了sockaddr_in結構這一數據類型中的IP地址域和端口域(但不包括sin_family域)。考慮到一個應用程序通常用與"時間"服務對應的端口來和服務器連接,而服務器提供某種機制來通知用户使用另一端口。因此getservbyname()函數返回的端口號已經是網絡順序了,可以直接用來組成一個地址,而不需要進行轉換。然而如果用户輸入一個數,而且指定使用這一端口號,應用程序則必須在使用它建立地址以前,把它從主機順序轉換成網絡順序(使用htons()函數)。相應地,如果應用程序希望顯示包含於某一地址中的端口號(例如從getpeername()函數中返回的),這一端口號就必須在被顯示前從網絡順序轉換到主機順序(使用ntohs()函數)。由於Intel處理器和Internet的字節順序是不同的,上述的轉換是無法避免的,應用程序的編寫者應該使用作為WindowsSocketsAPI一部分的標準的轉換函數,而不要使用自己的轉換函數代碼。因為將來的WindowsSockets實現有可能在主機字節順序與網絡字節順序相同的機器上運行。因此只有使用標準的轉換函數的應用程序是可移植的。
在MFC中MS為套接口提供了相應的類CAsyncSocketCSocket,CAsyncSocket提供基於異步通信的套接口封裝功能,CSocket則是由CAsyncSocket派生,提供更加高層次的功能,例如可以將套接口上發送和接收的數據和一個文件對象(CSocketFile)關聯起來,通過讀寫文件來達到發送和接收數據的目的,此外CSocket提供的通信為同步通信,數據未接收到或是未發送完之前調用不會返回。此外通過MFC類開發者可以不考慮網絡字節順序和忽略掉更多的通信細節。
在一次網絡通信/連接中有以下幾個參數需要被設置:本地IP地址-本地端口號-對方端口號-對方IP地址。左邊兩部分稱為一個半關聯,當與右邊兩部分建立連接後就稱為一個全關聯。在這個全關聯的套接口上可以雙向的交換數據。如果是使用無連接的通信則只需要建立一個半關聯,在發送和接收時指明另一半的參數就可以了,所以可以説無連接的通信是將數據發送到另一台主機的指定端口。此外不論是有連接還是無連接的通信都不需要雙方的端口號相同。
在創建CAsyncSocket對象時通過調用
BOOLCAsyncSocket::Create(UINTnSocketPort=0,intnSocketType=SOCK_STREAM,longlEvent=FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT|FD_CLOSE,LPCTSTRlpszSocketAddress=NULL)通過指明lEvent所包含的標記來確定需要異步處理的事件,對於指明的相關事件的相關函數調用都不需要等待完成後才返回,函數會馬上返回然後在完成任務後發送事件通知,並利用重載以下成員函數來處理各種網絡事件:標記事件需要重載的函數
FD_READ有數據到達時發生voidOnReceive(intnErrorCode);
FD_WRITE有數據發送時產生voidOnSend(intnErrorCode);
FD_OOB收到外帶數據時發生voidOnOutOfBandData(intnErrorCode);
FD_ACCEPT作為服務端等待連接成功時發生voidOnAccept(intnErrorCode);
FD_CONNECT作為客户端連接成功時發生voidOnConnect(intnErrorCode);
FD_CLOSE套接口關閉時發生voidOnClose(intnErrorCode);
我們看到重載的函數中都有一個參數nErrorCode,為零則表示正常完成,非零則表示錯誤。通過intCAsyncSocket::GetLastError()可以得到錯誤值
下面我們看看套接口類所提供的一些功能,通過這些功能我們可以方便的建立網絡連接和發送數據。
BOOLCAsyncSocket::Create(UINTnSocketPort=0,intnSocketType=SOCK_STREAM,longlEvent=FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT|FD_CLOSE,LPCTSTRlpszSocketAddress=NULL);用於創建一個本地套接口,其中nSocketPort為使用的端口號,為零則表示由系統自動選擇,通常在客户端都使用這個選擇。nSocketType為使用的協議族,SOCK_STREAM表明使用有連接的服務,SOCK_DGRAM表明使用無連接的數據報服務。lpszSocketAddress為本地的IP地址,可以使用點分法表示如10.1.1.3。
BOOLCAsyncSocket::Bind(UINTnSocketPort,LPCTSTRlpszSocketAddress=NULL)作為等待連接方時產生一個網絡半關聯,或者是使用UDP協議時產生一個網絡半關聯。
BOOLCAsyncSocket::Listen(intnConnectionBacklog=5)作為等待連接方時指明同時可以接受的連接數,請注意不是總共可以接受的連接數。
BOOLCAsyncSocket::Accept(CAsyncSocket&rConnectedSocket,SOCKADDR*lpSockAddr=NULL,int*lpSockAddrLen=NULL)作為等待連接方將等待連接建立,當連接建立後一個新的套接口將被創建,該套接口將會被用於通信。
BOOLCAsyncSocket::Connect(LPCTSTRlpszHostAddress,UINTnHostPort);作為連接方發起與等待連接方的連接,需要指明對方的IP地址端口號
voidCAsyncSocket::Close();關閉套接口。
intCAsyncSocket::Send(constvoid*lpBuf,intnBufLen,intnFlags=0)
intCAsyncSocket::Receive(void*lpBuf,intnBufLen,intnFlags=0);在建立連接後發送和接收數據,nFlags為標記位,雙方需要指明相同的標記。
intCAsyncSocket::SendTo(constvoid*lpBuf,intnBufLen,UINTnHostPort,LPCTSTRlpszHostAddress=NULL,intnFlags=0)
intCAsyncSocket::ReceiveFrom(void*lpBuf,intnBufLen,CString&rSocketAddress,UINT&rSocketPort,intnFlags=0);對於無連接通信發送和接收數據,需要指明對方的IP地址端口號,nFlags為標記位,雙方需要指明相同的標記。
我們可以看到大多數的函數都返回一個布爾值表明是否成功。如果發生錯誤可以通過intCAsyncSocket::GetLastError()得到錯誤值
由於CSocketCAsyncSocket派生所以擁有CAsyncSocket的所有功能,此外你可以通過BOOLCSocket::Create(UINTnSocketPort=0,intnSocketType=SOCK_STREAM,LPCTSTRlpszSocketAddress=NULL)來創建套接口,這樣創建的套接口沒有辦法異步處理事件,所有的調用都必需完成後才會返回。
在上面的介紹中我們看到MFC提供的套接口類屏蔽了大多數的細節,我們只需要做很少的工作就可以開發出利用網絡進行通信的軟件。