網絡程式設計知識基礎
8.1
程序間通訊,經過發展,最後迎來了一個新的階段——網絡通訊
網絡通訊其實是網絡域套接字通信(socket)
即位于兩個不同主機上的,2個程序之間的 通信
上 api
中 網卡驅動
下 網卡
學Linux的網絡程式設計三個層次:
1 低級:直接基于socket程式設計,比較難,要設定的東西是很多的
2 進階:基于網絡通信應用架構,封裝使得程式設計更簡單
3 更進階:基于http和網絡控件的傻瓜式程式設計。
我們在這裡學的是第一種,較為困難的程式設計,因為這種程式設計是無限可能的
8.2
網絡發展史
單機階段 1960’
主機是一個大裝置,外接打字機和鍵盤就可以構成一個終端。
因為當時計算機很少,根本沒有通訊的需求,是以多個終端就是當時的終極目标
打字機+鍵盤構成的終端,當時稱作“telleytype”,簡稱TTY,這個簡寫沿用至今
區域網路階段
開始研究多個主機間的通訊問題
最早用的是串行口,但是有個問題是速度低而且不易組網,于是後來發明了集線器
廣域網階段
區域網路與區域網路之間的通訊
移動網際網路階段
1997’ - 現在
2015年開始進入成熟階段,相關工作要求變高,職位變少
物聯網階段
即将到來的萬物相連階段
三大網絡:電信網,電視網絡,網際網路
趨勢:網際網路将慢慢取代其他網絡
網絡通訊的媒介
有線:雙絞線,同軸電纜,光纖
無線:wifi,GPRS,3G/4G/5G,華為把5G搞出來了,另外還有半死不活的zigbee
8.3 網絡裝置
1 網卡
這個一個可以內建,也可以擴充的子產品,作用就是上網=v=
1 連接配接外部網絡
2 串轉并
3 封包與拆包
4 網絡資料緩存 和 速率适配
2 集線器hub
1 信号的中繼放大,避免信号衰減
2 區域網路組網,以廣播方式工作
但注意:不可以連接配接外網
3 交換機
進階集線器,廣播方式發生改變,不再像集線器一樣挨個發,而是根據ip位址進行判斷
4 路由器
區域網路和外網連接配接的接口,連接配接多個不同網段的裝置,類似網關
他的核心功能就是提供外網
路由器由于是内部區域網路、外部廣域網的接口,是以他配備了2個網卡,一個用做網關,一個用做節點
對内:連接配接外網
對外:劃分子網,DHCP服務
關于DNS服務:域名解析服務
域名:www.kkqqq.com 即是ip位址的别名。
DNS提供域名和ip位址之間的轉換服務,是以域名是需要購買的。
8.5 DHCP 和 NAT
DHCP動态主機配置協定
IP位址可以靜态設定,也可以動态配置設定
動态配置設定是區域網路内DHCP伺服器提供的,路由器就有這個功能
我記得理工大學的andbusiness就有一個DHCP由于手機裝置太多導緻連不上網的問題,這個問題的解決方法就是使用靜态IP,這樣一來就不使用自動配置設定的IP位址。
DHCP的優點:友善接入和斷開,有限的IP位址得到充分利用。
NAT網絡位址轉換協定
IP位址分為公網位址和私網位址
區域網路内主機向外網發送資料包時,路由器将區域網路主機的内網IP替換為外網IP,這個過程就叫NAT
他是一種給ipv4打更新檔的方法,最終解決ip不夠的話還是要看ipv6。
NAT穿透
NAT就像一堵牆,192.168.2.1和另一個區域網路的192.168.2.1不能直接相連
迅雷是一種點對點(P2P)的下載下傳方式
我們下載下傳的資源其實是從周圍的、距離我們較近的其他有這個資源的電腦上擷取的
資源下載下傳時候的32/267 32代表我們實際連接配接上的資源,267是總資源
要想實作P2P,那麼就需要NAT穿透。
伺服器幫我們做了中介,幫我們打通了NAT的牆,這個技術就是NAT穿透
8.6 IP
ip在人機互動時候是點分十進制的,實際上是int型的
0xC0A80166 32位二進制方式
192.168.2.1 點分十進制
轉換過程中有一些api,專門用來做顯示轉換。
一台主機包含在一個網絡中的,找到這個主機要先找到他所在的網絡
IP位址 = 網絡位址 + 主機位址
譬如可以
8位表示網絡,24位表示主機位址
16位表示網路,16位表示主機位址
表示網絡部分、主機部分各自占多少位,要看子網路遮罩。子網路遮罩為1的位代表網絡位址
子網路遮罩255 255 255 0時,代表前24位是網絡位址,後8位是主機位址
常見的IP位址
A類
B類
C類
特殊IP位址:
127.0.0.0 用來做回環測試:網卡自己發自己收,測試網卡裝置是否可用
差別就是網絡位址和主機位址所占長度不同
如何判斷兩個ip位址是否在同一個子網内?
網絡辨別 = IP位址 & 子網路遮罩
若網絡辨別相同。那麼證明兩個IP位址在同一子網
============================================================
9.1 Linux網絡程式設計架構
注意:這個層次是比較複雜的,而且分層的感覺比較明顯。
TCP協定、socket接口
後面我們會學自己寫一個伺服器,能夠讓兩端連接配接上。當然完整的伺服器需要什麼,會點到為止。
深入學習網絡程式設計,就差不多要看書了
做什麼,我們再去深入研究什麼。
網絡是分層的
OSI 7層網絡模型
目的:解決整體的複雜性
具體表現:不一定分7層,如TCP隻有4層
TCP/IP協定引入:
TCP/IP是使用最多的網絡協定實作
上層程序在網絡通訊的時候,也是有一個定向功能的。QQ和QQ通信的時候,是有辦法精确到程序裡面去的。
在上層是一個獨特的層次,他不用考慮下層的問題,不管你什麼裝置到底用的是wifi還是4G。
Tips:關于網絡的學習:應該是學哪個層次就深入哪個。我們的學習重點是API+APP。關注的重點也是應用層,了解傳輸層。
網絡驅動、網卡相關和通訊相關的問題我們暫不考慮。
研究網絡通信的時候,一定是在同一層次上研究。是講應用都講應用。一個主機的應用和另一個主機的驅動是沒有任何話可以說的,因為這毫無意義。
BS和CS
BS架構 浏覽器伺服器架構 browser 多用戶端集于浏覽器 後
CS架構 用戶端伺服器架構 client-server 迅雷、網盤、QQ 先
9.2 TCP
1 位于傳輸層,對上服務socket,對下服務ip
2 面向連接配接,需要先建立連接配接
3 可靠傳輸
TCP保證可靠的方法:
1 握手
2 ack和丢包重傳
3 資料附帶校驗防止傳輸損壞
4 滑動視窗技術,根據帶寬适配速率
5 封包編号順序校驗
TCP的握手
握手的次數設計,取決于成本和可靠程度。握手越多成本越高,也越可靠。
[建立連接配接]
建立連接配接3次握手
伺服器listen時,用戶端connect
[關閉連接配接]
關閉連接配接4次握手
雙方任意一方都可以主動關閉
應用層寫代碼的時候,是不用管握手過程的,這些協定已經被傳輸層封裝好了。
建立連接配接的過程
伺服器端:
socket 建立套接字
bind 本地綁定
listen 進行監聽
用戶端:
socket 建立套接字
connect 發起連接配接
伺服器端:同意連接配接
8.6 Socket程式設計接口介紹
1、建立連接配接
socket(int 網絡域 , int type , int協定) //非常類似open
網絡域: 宏定義的ipv4或ipv6
type: 三類宏定義
SOCK_STREAM //TCP網絡
SOCK_DGRAM //UDP網絡
SOCK_SEQPACKET
協定: 預設0
bind(int socket , const struct sockaddr * address , len) //類似fcntl,綁定本地ip
listen(int socket , int backlog)
backlog: 監聽幾個
connect(int socket, 目的ip, len)
2、發送和接收函數
send(int socket, buf,len,int flag)
flag: 平時設定為0,即實作write()的功能,特殊協定時會使用到其他
recv(int socket, buf,len,int flag)
flag: 平時設定為0,即實作write()的功能,特殊協定時會使用到其他
3、輔助型函數
不支援ipv6的三個函數
inet_aton
inet_addr 點分十進制 → int格式
inet_ntoa
滋瓷ipv6的兩個函數
inet_ntop 32位 → 點分十進制 n代表net
inet_pton 32位 → 點分十進制 p當作person了解,其實是指針,字元格式的意思
13:27 2016/12/7
4、相關結構體
在/usr/include 下,netinet/in.c中,有對結構體的聲明
typedef u32_t in_addr_t;
struct in_addr
{
in_addr_t s_addr;
}
struct sockaddr_in //封裝ipv4的
{
in_port_t sin_port; //端口号
struct in_addr sin_addr; //ip位址
}
struct sockaddr這個“ip位址标準結構體”實際上隻是形參,是不存在的,他在實際應用過程中,會被替換為
struct sockaddr_in
或者
struct sockaddr_in6
5、補充一點:網絡位元組序
就是大端模式,網絡傳輸中,不同大小端的 裝置,都要遵從大端模式。
實戰1 CS機制
網絡之間用bind的原因
bind綁定的是 套接字 與 IP位址+端口号
網絡程序與網絡程序之間是不好直接通信的。因為根據IP位址僅僅能找到哪個裝置,而不是哪個程序。
網絡傳輸過程中是找不到目标程序的,這個時候就需要端口号port來為我們指引,是哪一個程序。、
伺服器
socket 傳回值fd =3(監聽fd,專門用來監聽,但是不能讀寫)
bind
listen
accept 傳回值ret =4(連接配接fd,用來和連接配接另一端的程式進行讀寫操作)
用戶端
socket
connect
htonl
host to net long 4位元組
htons
host to net short 2位元組
雙向通信:
用戶端發送 & 伺服器接收
伺服器發送 & 用戶端接收
伺服器:
WHILE1
ret = recv(clifd , recvbuf , sizeof(recvbuf) , );
printf recvbuf
memset
用戶端
WHILE1
ret = send(sockfd , sendbuf , sizeof(sendbuf) , );
printf recvbuf
memset
雙方自由收發:異步通信,需要一個通信約定完成同步。需要依靠應用層協定解決。