1. 概念:
通訊端(socket)是網路IPC介面, 進程能夠使用該介面和其他進程通訊. 通過該介面, 其他進程運行位置是透明的, 它們可以在同一台電腦上也可以在不同電腦上. 也就是說, 它支援電腦內的處理序間通訊和電腦之間的處理序間通訊.
Socket介面可以採用許多不同的網路通訊協定, 但我們主要討論的只是網路通訊標準: TCP/IP協議棧.
2. Socket描述符:
Linux下的socket描述符的使用就象Linux系統中檔案描述符的使用一樣, 在本質上它也是用檔案描述符實現的, 處理檔案描述符的函數(如read, write)也可以處理socket描述符.
Socket是通訊端點的抽象, 要建立一個socket, 可以調用socket函數:
- 標頭檔: <sys/socket.h>
- 原型: int socket(int domain, int type, int protocol);
- 傳回值: 成功返回socket描述符, 出錯返回-1.
- 參數:
- domain: 描述通訊的特徵, 用地址族(Address Family)表示, 常用的地址族有:
- AF_INET: IPv4 Internet
- AF_INET6: IPv6 Internet
- AF_UNIX/AF_LOCAL: 本地UNIX
- AF_UNSPEC: 未指定
- type: 描述socket的類型, 在實現中可以自由增加對其他類型的支援, 常用socket類型有:
- SOCK_DGRAM: 長度固定的, 不需連線的不可靠報文傳遞.
- SOCK_RAW: IP協議的資料報介面.
- SOCK_SEQPACKET: 長度固定, 有序, 可靠的連線導向報文傳遞.
- SOCK_STREAM: 有序, 可靠, 雙向的連線導向位元組流.
- protocol: 通常是0, 表示按給定的domain和type類型選擇預設協議.
- AF_INET + SOCK_STREAM預設協議是TCP(傳輸控制通訊協定)
- AF_INET + SOCK_DGRAM預設協議是UDP(使用者資料包通訊協定)
調用socket與調用open類似, 而不再需要該描述符時, 調用close來關閉.
3. UDP和TCP:
①UDP: 提供的是不需連線的服務. 資料報是一種自包含報文, 發送資料就象給某人郵寄信件:
- 每封信包含接收者地址;
- 可以郵寄很多信, 但不能保證投遞的順序;
- 信件可能丟失在路上;
- 每封信件可能送達不同的接收者.
相比之下:
②TCP: 提供的是有已連線的服務. 使用這種服務的協議通訊就象打電話:
- 需要通過電話建立一個串連;
- 每個串連是端到端的通訊通道;
- 會話中不包含地址資訊.
4. Socket類型(type參數)的區別:
- SOCK_DGRAM通訊時不需要串連, 只需要送出一個報文到指定地址的socket.
- SOCK_STREAM要求交換資料前, 在本地socket和與之通訊的遠程socket之間建立一個串連.
- SOCK_SEQPACKET與SOCK_STREAM類似, 但從socket得到的是基於報文的服務而不是位元組流的服務.
- SOCK_RAW提供一個資料報介面使用者直接存取下面的網路層(IP層). 使用這個介面時, 應用程式負責構造自己的協議首部, 因為傳輸協議(TCP/UDP)被繞過了. 當建立一個原始socket時需要有超級使用者特權, 防止惡意程式繞過內建的安全機制來建立報文.
5. 雙向通訊:
socket通訊是雙向的, 可以採用函數shutdown來禁止socket上的輸入/輸出:
- 標頭檔: <sys/socket.h>
- 原型: int shutdown(int sockfd, int how);
- 傳回值: 成功返回0, 出錯返回-1.
- 參數:
- sockfd: 通過socket函數建立的socket描述符.
- how:
- SHUT_RD: 關閉讀端, 無法從socket讀取資料.
- SHUT_WR: 關閉寫端, 無法從socket發送資料.
- SHUT_RDWR: 同時無法讀取和發送資料.
- 說明: shutdown和close是有區別的, 作用也是不等的.
- 首先, close只有在最後一個引用被關閉時才釋放端點, 比如: (使用dup)複製一個socket, socket直到關閉了最後一個引用它的檔案描述符之後才會被釋放. 而shutdown允許使一個socket處於不活動狀態, 無論它的引用計數是多少.
- 其次, 關閉雙向通訊中的一個方向.