套接字是一種通訊機制(通訊的兩方的一種約定),憑藉這種機制,不同主機之間的程序可以進行通訊。我們可以用套接字中的相關函式來完成通訊過程。
套接字的特性有三個屬性確定,它們是:域(domain),型別(type),和協議(protocol)。
#include
#include
intsocket
(int domain,
int type,
int protocol)
;
域指定套接字通訊中使用的網路介質。最常見的套接字域是af_inet(ipv4)或者af_inet6(ipv6),它是指 internet 網路,許多 linux 區域網使用的都是該網路,當然,網際網路自身用的也是它。
流套接字用於提供面向連線、可靠的資料傳輸服務。該服務將保證資料能夠實現無差錯、無重**送,並按順序接收。流套接字之所以能夠實現可靠的資料服務,原因在於其使用了傳輸控制協議,即tcp(the transmission control protocol)協議。
資料報套接字提供了一種無連線的服務。該服務並不能保證資料傳輸的可靠性,資料有可能在傳輸過程中丟失或出現資料重複,且無法保證順序地接收到資料。資料報套接字使用udp(user datagram protocol)協議進行資料的傳輸。由於資料報套接字不能保證資料傳輸的可靠性,對於有可能出現的資料丟失情況,需要在程式中做相應的處理。
原始套接字與標準套接字(標準套接字指的是前面介紹的流套接字和資料報套接字)的區別在於:原始套接字可以讀寫核心沒有處理的ip資料報,而流套接字只能讀取tcp協議的資料,資料報套接字只能讀取udp協議的資料。因此,如果要訪問其他協議傳送資料必須使用原始套接字。
使用預設協議;
使用tcp協議;
使用udp協議;
每個 socket 被建立後,都會分配兩個緩衝區,輸入緩衝區和輸出緩衝區。
write()/send() 並不立即向網路中傳輸資料,而是先將資料寫入緩衝區中,再由tcp協議將資料從緩衝區傳送到目標機器。一旦將資料寫入到緩衝區,函式就可以成功返回,不管它們有沒有到達目標機器,也不管它們何時被傳送到網路,這些都是tcp協議負責的事情。
read()/recv() 函式也是如此,也從輸入緩衝區中讀取資料,而不是直接從網路中讀取。
【對於tcp套接字(預設情況下),當使用 write()/send() 傳送資料時】:
1. 首先會檢查緩衝區,如果緩衝區的可用空間長度小於要傳送的資料,那麼 write()/send() 會被阻塞(暫停執行),直到緩衝區中的資料被傳送到目標機器,騰出足夠的空間,才喚醒 write()/send() 函式繼續寫入資料;
2. 如果tcp協議正在向網路傳送資料,那麼輸出緩衝區會被鎖定,不允許寫入,write()/send() 也會被阻塞,直到資料傳送完畢緩衝區解鎖,write()/send() 才會被喚醒。如果tcp協議正在向網路傳送資料,那麼輸出緩衝區會被鎖定,不允許寫入,write()/send() 也會被阻塞,直到資料傳送完畢緩衝區解鎖,write()/send() 才會被喚醒;
3. 如果要寫入的資料大於緩衝區的最大長度,那麼將分批寫入。如果要寫入的資料大於緩衝區的最大長度,那麼將分批寫入;
4. 直到所有資料被寫入緩衝區 write()/send() 才能返回。直到所有資料被寫入緩衝區 write()/send() 才能返回。
【當使用 read()/recv() 讀取資料時】:
1. 首先會檢查緩衝區,如果緩衝區中有資料,那麼就讀取,否則函式會被阻塞,直到網路上有資料到來;
2. 如果要讀取的資料長度小於緩衝區中的資料長度,那麼就不能一次性將緩衝區中的所有資料讀出,剩餘資料將不斷積壓,直到有 read()/recv() 函式再次讀取。如果要讀取的資料長度小於緩衝區中的資料長度,那麼就不能一次性將緩衝區中的所有資料讀出,剩餘資料將不斷積壓,直到有 read()/recv() 函式再次讀取;
3. 直到讀取到資料後 read()/recv() 函式才會返回,否則就一直被阻塞。
tcp傳送資料的大體過程:首先,tcp是有鏈結的可靠傳輸協議,所謂可靠也就是說保證客戶端傳送的資料服務端都能夠收到,並且是按序收到。那麼對於上面的問題就不可能存在資料的丟棄。那麼客戶端一直傳送資料越來越多怎麼辦?下面我們分析一下tcp的傳輸過程。
1. 資料首先由應用程式緩衝區複製到傳送端的輸出緩衝區(位於核心),注意這個過程是用類似write功能的函式完成的。有的人通常看到write成功就以為資料傳送到了對端主機,其實這是錯誤的,write成功僅僅表示資料成功的由應用程序緩衝區複製到了輸出緩衝區。
2.然後核心協議棧將輸出緩衝區中的資料傳送到對端主機,注意這個過程不受應用程式控制,而是傳送端核心協議棧完成,其中包括使用滑動視窗、用賽控制等功能。
3. 資料到達接收端主機的輸入緩衝區,注意這個接收過程也不受應用程式控制,而是由接收端核心協議棧完成,其中包括傳送ack確認等。
4.資料由套接字接收緩衝區複製到接收端應用程式緩衝區,注意這個過程是由類似read等函式來完成。
阻塞方式下,如果服務端一直sleep不接收資料,而客戶端一直write,也就是只能執行上述過程中的前三步,這樣最終結果肯定是接收端的輸入緩衝區和傳送端的輸出緩衝區都被填滿,這樣write就無法繼續將資料從應用程式複製到傳送端的輸出緩衝區了,從而使程序進入睡眠。
非阻塞情況下,服務端一直sleep,客戶端一直write資料的結果:開始客戶端write成功,隨著客戶端write,接收端的輸入緩衝區和傳送端的輸出緩衝區會被填滿。當傳送端的輸出緩衝區的可用空間小於write請求寫的位元組數時,write立即返回-1,並將errno置為ewouldblock。
參考:
套接字中緩衝區
1 mtu maximum transmission unit 最大傳輸單元,在資料鏈路層中,往往規定了mtu大小,ip層的資料報通過資料鏈路層如果大於mtu,將被分片,到達接收端ip層後再被重組。乙太網的mtu為1500位元組。2 mss maximum segment size 最大報文段,是t...
套接字的接受緩衝區及傳送緩衝區
1.套接字的接受緩衝區及傳送緩衝區 net.ipv4.tcp rmem 這個引數定義了tcp接收緩衝 用於tcp接收滑動視窗 的最小值 預設值 最大值 net.ipv4.tcp wmem 這個引數定義了tcp傳送緩衝 用於tcp傳送滑動視窗 的最小值 預設值 最大值 netdev max backl...
緩衝區設定 套接字緩衝區大小及限制
pv4資料報的最大值是65535位元組,包括ipv4首部。ipv6資料報的最大值是65575位元組,包括40位元組的首部。mtu ip資料報的最大傳輸單元,乙太網的mtu是1500位元組。ipv4要求的最小鏈路mtu是68位元組。ipv6要求的最小鏈路mtu是1280位元組。如果乙個ipv6的資料報...