什么是套接字?Socket基本介绍
什么是套接字?Socket基本介紹
- 一、什么是套接字?
- 二、套接字特性
- 三、套接字緩沖區(qū)
一、什么是套接字?
套接字是一種通信機制(通信的兩方的一種約定),socket屏蔽了各個協(xié)議的通信細節(jié),提供了tcp/ip協(xié)議的抽象,對外提供了一套接口,同過這個接口就可以統(tǒng)一、方便的使用tcp/ip協(xié)議的功能。這使得程序員無需關(guān)注協(xié)議本身,直接使用socket提供的接口來進行互聯(lián)的不同主機間的進程的通信。我們可以用套接字中的相關(guān)函數(shù)來完成通信過程。
發(fā)送方的發(fā)送數(shù)據(jù)的處理流程大致為:用戶空間 -> 內(nèi)核 -> 網(wǎng)卡 -> 網(wǎng)絡(luò)
在用戶態(tài)空間,調(diào)用發(fā)送數(shù)據(jù)接口 send/sento/wirte 等寫數(shù)據(jù)包,在內(nèi)核空間會根據(jù)不同的協(xié)議走不同的流程。以TCP為例,TCP是一種流協(xié)議,內(nèi)核只是將數(shù)據(jù)包追加到套接字的發(fā)送隊列中,真正發(fā)送數(shù)據(jù)的時刻,則是由TCP協(xié)議來控制的。TCP協(xié)議處理完成之后會交給IP協(xié)議繼續(xù)處理,最后會調(diào)用網(wǎng)卡的發(fā)送函數(shù),將數(shù)據(jù)包發(fā)送到網(wǎng)卡。
接收方的接收數(shù)據(jù)的處理流程大致為:網(wǎng)絡(luò) -> 網(wǎng)卡 -> 內(nèi)核(epoll等) -> 進程(業(yè)務(wù)處理邏輯)
網(wǎng)卡會通過輪詢或通知的方式接收數(shù)據(jù),Linux做了優(yōu)化,組合了通知和輪詢的機制,簡單來說,在CPU響應(yīng)網(wǎng)卡中斷時,不再僅僅是處理一個數(shù)據(jù)包就退出,而是使用輪詢的方式繼續(xù)嘗試處理新數(shù)據(jù)包,直到?jīng)]有新數(shù)據(jù)包到來,或者達到設(shè)置的一次中斷最多處理的數(shù)據(jù)包個數(shù)。數(shù)據(jù)離開網(wǎng)卡驅(qū)動之后就進入到了協(xié)議棧,經(jīng)過IP層、網(wǎng)絡(luò)層協(xié)議的處理,就會觸發(fā)IO讀事件,比如epoll的reactor模型中,就會觸發(fā)對應(yīng)的讀事件,然后回調(diào)對應(yīng)的IO處理函數(shù),數(shù)據(jù)之后會交給業(yè)務(wù)線程來處理,比如Netty的數(shù)據(jù)接收處理流程就是這樣的。
二、套接字特性
套接字的特性有三個屬性確定,它們是:域(domain),類型(type),和協(xié)議(protocol)。
域:指定套接字通信中使用的網(wǎng)絡(luò)介質(zhì)。最常見的套接字域是 AF_INET(IPv4)或者AF_INET6(IPV6),它是指 Internet 網(wǎng)絡(luò)。
類型:
- 流套接字(SOCK_STREAM):
流套接字用于提供面向連接、可靠的數(shù)據(jù)傳輸服務(wù)。該服務(wù)將保證數(shù)據(jù)能夠?qū)崿F(xiàn)無差錯、無重復(fù)發(fā)送,并按順序接收。流套接字之所以能夠?qū)崿F(xiàn)可靠的數(shù)據(jù)服務(wù),原因在于其使用了傳輸控制協(xié)議,即TCP - 數(shù)據(jù)報套接字(SOCK_DGRAM):
數(shù)據(jù)報套接字提供了一種無連接的服務(wù)。該服務(wù)并不能保證數(shù)據(jù)傳輸?shù)目煽啃?#xff0c;數(shù)據(jù)有可能在傳輸過程中丟失或出現(xiàn)數(shù)據(jù)重復(fù),且無法保證順序地接收到數(shù)據(jù)。數(shù)據(jù)報套接字使用UDP(User Datagram Protocol)協(xié)議進行數(shù)據(jù)的傳輸。 - 原始套接字(SOCK_RAW):
原始套接字與標準套接字(標準套接字指的是前面介紹的流套接字和數(shù)據(jù)報套接字)的區(qū)別在于:原始套接字可以讀寫內(nèi)核沒有處理的IP數(shù)據(jù)包,而流套接字只能讀取TCP協(xié)議的數(shù)據(jù),數(shù)據(jù)報套接字只能讀取UDP協(xié)議的數(shù)據(jù)。因此,如果要訪問其他協(xié)議發(fā)送數(shù)據(jù)必須使用原始套接字。
協(xié)議:IPPROTO_TCP,IPPROTO_UDP
三、套接字緩沖區(qū)
每個 socket 被創(chuàng)建后,都會分配兩個緩沖區(qū),輸入緩沖區(qū)和輸出緩沖區(qū)。write()/send() 并不立即向網(wǎng)絡(luò)中傳輸數(shù)據(jù),而是先將數(shù)據(jù)寫入緩沖區(qū)中,再由TCP協(xié)議將數(shù)據(jù)從緩沖區(qū)發(fā)送到目標機器。一旦將數(shù)據(jù)寫入到緩沖區(qū),函數(shù)就可以成功返回,不管它們有沒有到達目標機器,也不管它們何時被發(fā)送到網(wǎng)絡(luò),這些都是TCP協(xié)議負責(zé)的事情。read()/recv() 函數(shù)也是如此,也從輸入緩沖區(qū)中讀取數(shù)據(jù),而不是直接從網(wǎng)絡(luò)中讀取。
用戶程序緩沖區(qū)
用戶進程通過系統(tǒng)調(diào)用訪問系統(tǒng)資源的時候,需要切換到內(nèi)核態(tài),而這對應(yīng)一些特殊的堆棧和內(nèi)存環(huán)境,必須在系統(tǒng)調(diào)用前建立好。而在系統(tǒng)調(diào)用結(jié)束后,cpu會從核心模式切回到用戶模式,而堆棧又必須恢復(fù)成用戶進程的上下文。而這種切換就會有大量的耗時。
一些程序在讀取文件時,會先申請一塊內(nèi)存數(shù)組,稱為buffer,然后每次調(diào)用read,讀取設(shè)定字節(jié)長度的數(shù)據(jù),寫入buffer(用較小的次數(shù)填滿buffer)。之后的程序都是從buffer中獲取數(shù)據(jù),當(dāng)buffer使用完后,在進行下一次調(diào)用,填充buffer。所以說:用戶緩沖區(qū)的目的是為了減少系統(tǒng)調(diào)用次數(shù),從而降低操作系統(tǒng)在用戶態(tài)與核心態(tài)切換所耗費的時間。除了在進程中設(shè)計緩沖區(qū),內(nèi)核也有自己的緩沖區(qū)。
內(nèi)核緩沖區(qū)
當(dāng)一個用戶進程要從磁盤讀取數(shù)據(jù)時,內(nèi)核一般不直接讀磁盤,而是將內(nèi)核緩沖區(qū)中的數(shù)據(jù)復(fù)制到進程緩沖區(qū)中。但若是內(nèi)核緩沖區(qū)中沒有數(shù)據(jù),內(nèi)核會把對數(shù)據(jù)塊的請求,加入到請求隊列,然后把進程掛起,為其它進程提供服務(wù)。等到數(shù)據(jù)已經(jīng)讀取到內(nèi)核緩沖區(qū)時,把內(nèi)核緩沖區(qū)中的數(shù)據(jù)讀取到用戶進程中,才會通知進程。
你可以認為,read是把數(shù)據(jù)從內(nèi)核緩沖區(qū)復(fù)制到進程緩沖區(qū)。write是把進程緩沖區(qū)復(fù)制到內(nèi)核緩沖區(qū)。當(dāng)然,write并不一定導(dǎo)致內(nèi)核的寫動作,比如os可能會把內(nèi)核緩沖區(qū)的數(shù)據(jù)積累到一定量后,再一次寫入。這也就是為什么斷電有時會導(dǎo)致數(shù)據(jù)丟失。所以說內(nèi)核緩沖區(qū),是為了在OS級別,提高磁盤IO效率,優(yōu)化磁盤寫操作。
總結(jié)
以上是生活随笔為你收集整理的什么是套接字?Socket基本介绍的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: kubeadm join时出现错误:[E
- 下一篇: jstl tag