基於TCP與UDP的windows網絡編程

一、網絡字節順序與主機字節順序

不同的計算機存放多字節值的順序不同,有的機器在起始地址存放低位字節(低位先存),有的機器在起始地址存放高位字節(高位先存)。基於 Inter 的 CPU ,即使我們常用的 PC 機採用的是低位先存。爲保證數據的正確性,在網絡協議中需要指定網絡字節順序, TCP/IP 協議使用16位整數和32位整數的高位先存格式。由於不同計算機存放數據字節的順序不同,這樣發送數據後,即使接收方接收到該數據,也有可能無法查看所接收到的數據。所以在網絡中不同主機間進行通訊時,要統一採用網絡字節順序。

下面是 WinSockAPI 提供的幾個轉換函數:

u_long htonl(u_long hostlong);//將32位的主機字節序轉換爲32位的網絡字節序,htonl => host to net long

u_short htons(u_short hostshort);//將16位的主機字節序轉換爲16位的網絡字節序,htons => host to net short

u_long ntohl(u_long netlong);//將32位的網絡字節序轉換爲32位的主機字節序,ntohl => net to host long

u_short ntohs(u_short netshort);//將16位的網絡字節序轉換爲16位的主機字節序,ntohs => net to host short

二、套接字(socket)的類型

  • 流式套接字(SOCK_STREAM)
    提供面向連接,可靠的數據傳輸服務,數據無差錯,無重複的發送,且按發送順序接收。流式套接字實際上是基於 TCP 協議實現的。

  • 數據報套接字(SOCK_DGRAM)
    提供無連接服務。數據包以獨立包形式發送,不提供無錯保證,數據可能丟失或重複,並且接收順序混亂。數據報式套接字實際上是基於 UDP 協議實現的。

  • 原始套接字(SOCK_RAW)
    原始套接字可以讀寫內核沒有處理的 IP 數據包,而流套接字只能讀取 TCP 協議的數據,數據報套接字只能讀取 UDP 協議的數據。因此,如果要訪問其他協議發送數據必須使用原始套接字。

三、基於TCP(面向連接)的 socket 編程

基於 TCP(面向連接)的 socket 編程的服務器端程序流程如下:

  1. 創建一個套接字(socket)。
  2. 將套接字綁定到一個本地地址和端口上(bind)。
  3. 將套接字設置爲監聽模式,準備接收客戶的請求(listen)。
  4. 等待客戶請求的到來;當請求到來後,接受連接請求,返回一個新的對應與此連接的套接字(accept)。
  5. 用返回的套接字和客戶端進行通信(send/recv)。
  6. 返回,等待另一客戶請求。
  7. 關閉套接字。

基於TPC(面向連接)的 socket 編程的客戶端程序流程如下:

  1. 創建套接字(socket)。
  2. 向服務器發出連接請求(connect)。
  3. 和服務器端進行通信(send/recv)。
  4. 關閉套接字。

在服務器端,當調用 accept 函數時,程序就會等待,等待客戶調用 connect 函數發出連接請求,然後服務器端接受該請求,於是雙方就建立了連接。之後,服務器端和客戶端就可以利用 send 和 recv 函數進行通信了。注意,在客戶端不需要調用 bind 函數。因爲服務器需要接收客戶端的請求,所以必須告訴本地主機它打算在哪個 IP 地址和哪個端口上等待客戶請求,因此必須調用 bind 函數來實現這一功能。而對客戶端來說,當它發起連接請求,服務器接受該請求後,在服務器端就已經保存了該客戶端的 IP 地址和端口號的信息。這樣,對服務器端來說,一旦建立連接後,實際上已經保存了客戶端的 IP 地址和端口號信息,因此就可以利用返回的套接字調用 send/recv 函數與客戶端進行通信。

四、基於UDP(面向無連接)的 socket 編程

服務器端也叫做接收端,對於 UDP 的套接字來說,它的服務器端和客戶端這種概念不是很強化,我們也可以把服務器端,即先啓動的一端稱爲接收端,發送數據的一端稱爲客戶端。

接收端程序的編寫:

  1. 創建套接字(socket)。
  2. 將套接字綁定到一個本地地址和端口上(bind)。
  3. 等待接收數據(recvfrom)。
  4. 關閉套接字。

對於基於 UDP 的套接字編程,爲什麼仍要需要調用 bind 函數進行綁定呢?應注意,雖然面向無連接的 socket 編程無須建立連接,但是爲了完成這次通信,對於接收端來說,它必須先啓動以接收客戶端發送的數據,因此接收端必須告訴主機它在哪個地址和端口等待數據的到來,也就是說,接收端必須調用 bind 函數將套接字綁定到一個本地地址和端口上。

客戶端程序的編寫:

  1. 創建套接字(socket)。
  2. 向服務器發送數據(sendto)。
  3. 關閉套接字。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章