這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
什麼是socket?
網路上的兩個程式通過一個雙向的通訊串連實現資料的交換,這個串連的一端稱為一個socket。
我們知道兩個進程如果需要進行通訊最基本的一個前提能能夠唯一的標示一個進程,在本地進程通訊中我們可以使用PID來唯一標示一個進程,但PID只在本地唯一,網路中的兩個進程PID衝突幾率很大,這時候我們需要另闢它徑了,我們知道IP層的ip地址可以唯一標示主機,而TCP層協議和連接埠號碼可以唯一標示主機的一個進程,這樣我們可以利用ip地址+協議+連接埠號碼唯一標示網路中的一個進程,能夠唯一標示網路中的進程後,它們就可以利用socket進行通訊。
建立網路通訊串連至少要一對連接埠號碼(socket)。socket本質是編程介面(API),對TCP/IP的封裝,TCP/IP也要提供可供程式員做網路開發所用的介面,這就是Socket編程介面;HTTP是轎車,提供了封裝或者顯示資料的具體形式;Socket是發動機,提供了網路通訊的能力。
socket與http的區別
在網路七層架構中,http屬於應用程式層協議,圖
而socket是位於應用程式層和傳輸層之間的一個抽象層,是本來不存在與七層架構中的:圖
socket通訊流程是怎樣進行的?
socket的通訊流程:
流程解讀:
1. server端建立socket
2. server端綁定socket和連接埠號碼
3. server端監聽該連接埠號碼
4. server端啟動accept()接收來自client端的串連請求,此時有串連進入時會往後續執行,沒有連結則會阻塞在此
5. client端建立socket
6. client端根據server端的ip和port串連server端(tcp的三向交握)
7. 如果第6步串連成功,在server端將會收到一個串連,假如這個串連名叫conn
8. client端向server端發送資料
9. server端從conn中讀取到client端發送過來的資料
10. 任何一端都可以主動中斷連線
socket中傳輸資料出現的問題
粘包:當server端用一個buff接收資料,發現buff中除了一個完整的包之外還有其他的資料。
半包:server端未接收到一個完整的包,只接收到了一部分。
socket的封包與拆包
在實際開發中往往會封裝自己的資料,一般分為Head和Body,Head中除了封裝額外的資訊之外,還會封裝Body的長度在裡面。這樣就形成了如下資料:
Head{ //頭資訊 (總共佔用6個位元組)
One byte //第一個標誌 (1個位元組)
Two byte //第二個標誌 (1個位元組)
Length int32 //存放Body的資料長度 (4個位元組)
}
Body{ //訊息體 (總共佔用?+4個位元組)
Name []byte //名字 (佔用?個位元組)
Age int32 //年齡 (佔用4個位元組)
}
Data{
Head
Body
}
server端要對接收到的資料[]byte進行拆包以防止粘包和半包情況的發生。
註:Data這個資料結構在server端和client端都應保持一致
封包過程:
將一個封裝好的Data資料轉化成[]byte,然後發送。
拆包過程:
1. 迴圈從conn中讀取資料,每次迴圈都判斷接收到的資料是否>=6,若是,則表明接收完了Head,若否,繼續執行下一次迴圈,知道滿足條件
2. 接收完Head後,將前6個位元組的資料解析到Data的Head中,對於從conn接收到的資料長度減去6(得到的是接收到的Body資料的長度),判斷這個結果是否>=Head中Length,若否,迴圈繼續接收資料;若是,則解析出Length長度的資料放入Data的Body,自此之後的資料又重新用一個Data來解析並存放
這樣拆包就解決了粘包和半包的問題。
golang代碼實現
簡書貼代碼真是蛋疼,算了