TCP/IP 學習筆記(2)- 套接字類型與協議設置


上一篇文章我們簡單講了TCP服務端和客戶端程序的編寫,但是對於裏面函數並沒有具體的說明。接下來具體說明一下 socket 函數。

socket 函數主要用於創建套接字,它的基本形式如下:

  • int socket (int domain, int type, int protocel)
  • domain: 套接字中使用的協議族信息
  • type: 套接字傳輸類型信息
  • protocol: 計算機間通信中使用的協議信息
  • 返回值: 成功時返回文件描述符,失敗時返回-1

1. 協議族

socket 函數的第一個參數爲套接字中使用的協議分類信息,成爲協議族,可分爲如下幾類:

  • PF_INET : IPv4互聯網協議族
  • PF_INET6: IPv6互聯網協議族
  • PF_LOCAL : 本地通信的UNIX協議族
  • PF_PACKET : 底層套接字的協議族
  • PF_IPX : IPX Novell協議族

之前的例子中,使用的是 PF_INET 協議族,另外套接字中實際採用的最終協議信息是通過 socket 函數的第三個參數傳遞的。在指定的協議族範圍內通過第一個參數決定第三個參數。

2. 套接字類型

套接字類型指的是套接字數據的傳輸方式,即使用TCP還是UDP傳輸。

(1)面向連接的套接字(SOCK_STREAM)

如果向 socket 函數的第二個函數傳遞 SOCK_STREAM , 將創建面向連接套接字。面向連接套接字具有如下特點

  • 傳輸過程中數據不會丟失。
  • 按順序傳輸數據。
  • 傳輸的數據不存在數據邊界。
  • 套接字必須一一對應。

收發數據的套接字中具有緩衝區,通過套接字傳輸的數據保存在緩衝區中,因此收到數據並不意味之馬上調用 recv 函數,只要不超過緩衝區的數據容量,則有可能在數據填充滿緩衝後調用一次read函數讀取全部數據。也可能分多次read函數進行讀取。因此調用 readwrite 函數的次數沒有太大的意義。所以說 傳輸的數據是不存在數據邊界的

如果緩衝區的數據滿了會怎麼樣呢? 首先調用 read 函數讀取緩衝區的部分數據,如果 read 函數的讀取速度比接受的速度滿,則緩衝取可能被填滿。此時套接字無法再接受數據,但即使這樣也不會發生數據丟失,因此傳輸數據的套接字將停止傳輸。也就是說,面向連接的套接字會根據接收端的狀態傳輸數據,如果傳輸出錯還會重傳。

用一句話總結面向連接的套接字就是:
可靠的、按序傳輸的、基於字節的面向連接的數據傳輸方式的套接字

(2)面向消息的套接字(SOCK_DGRAM)

如果向 socket 函數的第二個參數傳遞 SOCK_DGRAM 參數,則創建面向消息的套接字。面向消息的套接字有如下特點:

  • 強調快速傳輸而非傳輸順序。
  • 傳輸的數據可能丟失也可能被銷燬。
  • 傳輸的數據有數據邊界。
  • 限制每次傳輸數據的大小。

面向消息的套接字比面向連接的套接字具有更快的傳輸速度,但是無法避免的數據丟失和銷燬。另外,每次傳輸數據大小具有一定的限制,並存在數據邊界。存在數據邊界意味着接收數據的次數和傳輸次數相同,總結面向消息的套接字一句話就是:
不可靠的、不按序傳遞的、以數據的高速傳輸爲目的的套接字。

3. 協議的最終選擇

下面介紹 socket 函數的最後一個參數,該參數決定最終採用的協議。前面的程序中,最後一個參數填的0,除非遇到如下情況:
同一協議族中存在多個數據傳輸方式相同的協議

在參數 PF_INETIPv4 網絡族中,SOCK_STREAM 面向連接的數據傳輸。滿足以上兩個條件的只有 IPPROTO_TCP,因此可以使用下面的方式創建 TCP套接字
int tcpsocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

SOCK_DGRAM 指向的面向消息的傳輸方式中,滿足以上條件的只有 IPPROTO_UDP, 因此可以使用下面的方式創建 UDP套接字
int udpsocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);

4. Windows中的socket函數

上面介紹的爲 Linuxsocket函數,windows中socket函數跟Linux中的使用是相同,唯一不同的是返回值,這裏再次給出 socket 函數的聲明:

  • #include <winsock2.h>
  • SOCKET socket(int domain, int type, int protocel)
  • 返回值:成功返回socket句柄,失敗返回 INVALID_SOCKET
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章