C++中socket編程基礎詳解

來源:互聯網
上載者:User

對於SOCKET在這裡我不想究其曆史,我只想說其時它是一種進程通訊的方式,簡言之就是調用這個網路程式庫的一些API函數就能實現分布在不同主機的相關進程之間的資料交換.

  SOCKET中首先我們要理解如下幾個定義概念:

  一是IP地址:IP Address我想很容易理解,就是依照TCP/IP協議分配給本地主機的網路地址,就向兩個進程要通訊,任一進程要知道通訊對方的位置,位置如何來確定,就用對方的IP

  二是連接埠號碼:用來標識本地通訊進程,方便OS提交資料.就是說進程指定了對方進程的網路IP,但這個IP只是用來標識進程所在的主機,如何來找到運行在這個主機的這個進程呢,就用連接埠號碼.

  三是串連:指兩個進程間的通訊鏈路.

  四是半相關:網路中用一個三元組可以在全域唯一標誌一個進程:

  (協議,本地地址,本地連接埠號碼)

  這樣一個三元組,叫做一個半相關,它指定串連的每半部分。

  五是全相關

  一個完整的網間進程通訊需要由兩個進程組成,並且只能使用同一種高層協議。也就是說,不可能通訊的一端用TCP協議,而另一端用UDP協議。因此一個完整的網間通訊需要一個五元組來標識:

  (協議,本地地址,本地連接埠號碼,遠地地址,遠地連接埠號碼)

  這樣一個五元組,叫做一個相關(association),即兩個協議相同的半相關才能組合成一個合適的相關,或完全指定組成一串連。

  客戶/伺服器模式

  在TCP/IP網路應用中,通訊的兩個進程間相互作用的主要模式是客戶/伺服器模式(Client/Server model),即客戶向伺服器發出服務要求,伺服器接收到請求後,提供相應的服務。客戶/伺服器模式的建立基於以下兩點:首先,建立網路的起因是網路中軟硬體資源、運算能力和資訊不均等,需要共用,從而造就擁有眾多資源的主機提供服務,資源較少的客戶請求服務這一非對等作用。其次,網間進程通訊完全是非同步,相互連信的進程間既不存在父子關係,又不共用記憶體緩衝區,因此需要一種機製為希望通訊的進程間建立聯絡,為二者的資料交換提供同步,這就是基湧紀紀戶/伺服器模式的TCP/IP。

  客戶/伺服器模式鑰紀紀作過程中採取的是主動請求方式:

  首先伺服器方要先啟動,並根據請求提供相應服務:

  1. 開啟一通訊通道並告知本地主機,它願意在某一公認地址上(周知口,如FTP為21)接收客戶請求;

  2. 等待客戶請求到達該連接埠;

  3. 接收到重複服務要求,處理該請求並發送應答訊號。接收到並發服務要求,要啟用一新進程來處理這個客戶請求(如UNIX系統中用fork、exec)。新進程處理此客戶請求,並不需要對其它請求作出應答。服務完成後,關閉此新進程與客戶的通訊鏈路,並終止。

  4. 返回第二步,等待另一客戶請求。

  5. 關閉伺服器

  客戶方:

  1. 開啟一通訊通道,並串連到伺服器所在主機的特定連接埠;

  2. 向伺服器發服務要求報文,等待並接收應答;繼續提出請求......

  3. 請求結束後關閉通訊通道並終止。

  從上面所描述過程可知:

  1. 客戶與伺服器處理序的作用是非對稱的,因此編碼不同。

  2. 服務進程一般是先湧紀紀戶請求而啟動的。只要系統運行,該服務進程一直存在,直到正常或強迫終止。

  介紹完基礎知識,下面就介紹一些API函數:

  建立通訊端──socket()

  應用程式在使用通訊端前,首先必須擁有一個通訊端,系統調用socket()嚮應用程式提供建立通訊端的手段,其調用格式如下:

  SOCKET PASCAL FAR socket(int af, int type, int protocol);

  該調用要接收三個參數:af、type、protocol。參數af指定通訊發生的地區,:AF_UNIX、AF_INET、AF_NS等,而DOS、 WINDOWS中僅支援AF_INET,它是網際網地區。因此,地址族與協議族相同。參數type 描述要建立的通訊端的類型。這裡分三種:一是TCP流式通訊端(SOCK_STREAM)提供了一個連線導向、可靠的Data Transmission Service,資料無差錯、無重複地發送,且按發送順序接收。內設流量控制,避免資料流超限;資料被看作是位元組流,無長度限制。檔案傳送協議(FTP)即使用流式通訊端。

  二是資料報式通訊端(SOCK_DGRAM)提供了一個無串連服務。資料包以獨立包形式被發送,不提供無錯保證,資料可能丟失或重複,並且接收順序混亂。網路檔案系統(NFS)使用資料報式通訊端。三是原始式通訊端 (SOCK_RAW)該介面允許對較低層協議,如IP、ICMP直接存取。常用於檢驗新的協議實現或訪問現有服務中配置的新裝置.參數protocol說明該通訊端使用的特定協議,如果調用者不希望特別指定使用的協議,則置為0,使用預設的串連模式。根據這三個參數建立一個通訊端,並將相應的資源分派給它,同時返回一個整型通訊端號。因此,socket()系統調用實際上指定了相關五元組中的“協議”這一元。

  指定本地地址──bind()

  當一個通訊端用socket()建立後,存在一個名字空間(地址族),但它沒有被命名。bind()將通訊端地址(包括本地主機地址和本地連接埠地址)與所建立的通訊端號聯絡起來,即將名字賦予通訊端,以指定本地半相關。其調用格式如下:

  int PASCAL FAR bind(SOCKET s, const struct sockaddr FAR * name, int namelen);

  參數s是由socket()調用返回的並且未作串連的通訊端描述符(通訊端號)。參數name 是賦給通訊端s的本地地址(名字),其長度可變,結構隨通訊域的不同而不同。namelen表明了name的長度.如果沒有錯誤發生,bind()返回0。否則返回SOCKET_ERROR。

  建立通訊端串連──connect()與accept()

  這兩個系統調用用於完成一個完整相關的建立,其中connect()用於建立串連。不需連線的通訊端進程也可以調用connect(),但這時在進程之間沒有實際的報文交換,調用將從本地作業系統直接返回。這樣做的優點是程式員不必為每一資料指定目的地址,而且如果收到的一個資料報,其目的連接埠未與任何通訊端建立“串連”,便能判斷該端靠紀紀可操作。而accept()用於使伺服器等待來自某客戶進程的實際串連。

  connect()的調用格式如下:

  int PASCAL FAR connect(SOCKET s, const struct sockaddr FAR * name, int namelen);

  參數s是欲建立串連的本地通訊端描述符。參數name指出說明對方通訊端地址結構的指標。對方通訊端地址長度由namelen說明。

  如果沒有錯誤發生,connect()返回0。否則傳回值SOCKET_ERROR。在連線導向的協議中,該調用導致本地系統和外部系統之間串連實際建立。

  由於地址族總被包含在通訊端地址結構的前兩個位元組中,並通過socket()調用與某個協議族相關。因此bind()和connect()無須協議作為參數。

  accept()的調用格式如下:

  SOCKET PASCAL FAR accept(SOCKET s, struct sockaddr FAR* addr, int FAR* addrlen);

  參數s為本地通訊端描述符,在用做accept()調用的參數前應該先調用過listen()。addr 指向客戶方通訊端地址結構的指標,用來接收串連實體的地址。addr的確切格式由通訊端建立時建立的地址族決定。addrlen 為客戶方通訊端地址的長度(位元組數)。如果沒有錯誤發生,accept()返回一個SOCKET類型的值,表示接收到的通訊端的描述符。否則傳回值INVALID_SOCKET。

  accept() 用於連線導向伺服器。參數addr和addrlen存放客戶方的地址資訊。調用前,參數addr 指向一個初始值為空白的地址結構,而addrlen 的初始值為0;調用accept()後,伺服器等待從編號為s的通訊端上接受客戶串連請求,而串連請求是由客戶方的connect()調用發出的。當有串連請求到達時,accept()調用將請求串連隊列上的第一個客戶方通訊端地址及長度放入addr 和addrlen,並建立一個與s有相同特性的新通訊端號。新的通訊端可用於處理伺服器並發請求。

  四個通訊端系統調用,socket()、bind()、 connect()、accept(),可以完成一個完全五元相關的建立。socket()指定五元組中的協議元,它的用法與是否為客戶或伺服器、是否連線導向無關。bind()指定五元組中的本地二元,即本地主機地址和連接埠號碼,其用法與是否連線導向有關:在伺服器方,無論是否連線導向,均要調用 bind(),若採用連線導向,則可以不調用bind(),而通過connect()自動完成。若採用無串連,客戶方必須使用bind()以獲得一個唯一的地址。

  監聽串連──listen()

  此調用用於連線導向伺服器,表明它願意接收串連。listen()需在accept()之前調用,其調用格式如下:

  int PASCAL FAR listen(SOCKET s, int backlog);

  參數s標識一個本地已建立、尚未串連的通訊端號,伺服器願意從它上面接收請求。backlog表示請求串連隊列的最大長度,用於限制排隊請求的個數,目前允許的最大值為5。如果沒有錯誤發生,listen()返回0。否則它返回SOCKET_ERROR。

  listen()在執行調用過程中可為沒有調用過bind()的通訊端s完成所必須的串連,並建立長度為backlog的請求串連隊列。

  調用listen()是伺服器接收一個串連請求的四個步驟中的第三步。它在調用socket()分配一個流通訊端,且調用bind()給s賦於一個名字之後調用,而且一定要在accept()之前調用。

  資料轉送──send()與recv()

  當一個串連建立以後,就可以傳輸資料了。常用的系統調用有send()和recv()。

  send()調用用於鑰紀紀數s指定的已串連的資料報或流通訊端上發送輸出資料,格式如下:

  int PASCAL FAR send(SOCKET s, const char FAR *buf, int len, int flags);

  參數s為已串連的本地通訊端描述符。buf 指向存有發送資料的緩衝區的指標,其長度由len 指定。flags 指定傳輸控制方式,如是否發送帶外資料等。如果沒有錯誤發生,send()返回總共發送的位元組數。否則它返回SOCKET_ERROR。

  recv()調用用於s指定的已串連的資料報或流通訊端上接收輸入資料,格式如下:

  int PASCAL FAR recv(SOCKET s, char FAR *buf, int len, int flags);

  參數s 為已串連的通訊端描述符。buf指向接收輸入資料緩衝區的指標,其長度由len 指定。flags 指定傳輸控制方式,如是否接收帶外資料等。如果沒有錯誤發生,recv()返回總共接收的位元組數。如果串連被關閉,返回0。否則它返回SOCKET_ERROR。

  輸入/輸出多工──select()

  select() 調用用來檢測一個或多個通訊端的狀態。對每一個通訊端來說,這個調用可以請求讀、寫或錯誤狀態方面的資訊。請求給定狀態的通訊端集合由一個fd_set結構指示。在返回時,此結構被更新,以反映那些滿足特定條件的通訊端的子集,同時, select()調用返回滿足條件的通訊端的數目,其調用格式如下:

  int PASCAL FAR select(int nfds, fd_set FAR * readfds, fd_set FAR * writefds, fd_set FAR * exceptfds, const struct timeval FAR * timeout);

  參數nfds指明被檢查的通訊端描述符的範圍,此變數一般被忽略。

  參數readfds指向要做讀檢測的通訊端描述符集合的指標,調用者希望從中讀取資料。參數writefds 指向要做寫檢測的通訊端描述符集合的指標。 exceptfds指向要檢測是否出錯的通訊端描述符集合的指標。timeout指向select()函數等待的最大時間,如果設為NULL則為阻塞操作。select()返回包含在fd_set結構中已準備好的通訊端描述符的總數目,或者是發生錯誤則返回SOCKET_ERROR。

  關閉通訊端──closesocket()

  closesocket()關閉通訊端s,並釋放分配給該通訊端的資源;如果s涉及一個開啟的TCP串連,則該串連被釋放。closesocket()的調用格式如下:

  BOOL PASCAL FAR closesocket(SOCKET s);

  參數s待關閉的通訊端描述符。如果沒有錯誤發生,closesocket()返回0。否則傳回值SOCKET_ERROR。

  以上就是SOCKET API一些常用的API函數,下面我在介紹C/S模式就是客戶機/伺服器通訊模式,伺服器啟動服務並在相應連接埠內偵聽,客戶機開啟串連,完成通訊鏈路的建立後,雙方進行資料互動,完畢後關閉通訊端.

  好了,SOCKET基礎我們就介紹到這裡。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.