計算機網絡(基礎概念)
- 1 初識協議
- 1.1 協議分層
- 2 OSI七層模型
- 2.1 物理層
- 2.2 數據鏈路層
- 2.3 網絡層
- 2.4 傳輸層
- 2.5 應用層
- 3 TCP/IP協議族
- 3.1 什么是TCP/IP協議?
- 3.1.1 OS與網絡關系
- 4 網絡傳輸的基本流程
- 4.1 局域網
- 4.2 MAC地址
- 5 跨網絡傳輸
- 5.1 IP地址
- 6 Socket編程預備
- 6.1 源IP地址和目的IP地址
- 6.2 端口號
- 7 傳統層的典型代表
- 8 了解協議
- 8.1 協議
- 8.2 網絡字節序
- 9 socket 編程接口
- 9.1 socket 常用API
1 初識協議
協議的本質就是一種約定
總的來說,協議在生活中無處不在。
1.1 協議分層
協議本質上也是軟件,在設計上為了更好地模塊化、解耦合,也是被設計為層狀結構的
分層就是解耦合的有效方式,增強了代碼的可維護性
2 OSI七層模型
接下來我們只學習1-4層,其它層基本使用不到
2.1 物理層
負責光/電信號的傳遞方式. 比如現在以太網通用的網線(雙絞 線)、早期以太網采用的的同軸電纜(現在主要用于有線電視)、光纖, 現在的 wifi 無線網使用電磁波等都屬于物理層的概念。物理層的能力決定了最大傳輸速率、傳輸距離、抗干擾性等. 集線器(Hub)工作在物理層.
2.2 數據鏈路層
負責設備之間的數據幀的傳送和識別. 例如網卡設備的驅動、幀同步(就是說從網線上檢測到什么信號算作新幀的開始)、沖突檢測(如果檢測到沖突就自動重發)、數據差錯校驗等工作. 有以太網、令牌環網, 無線 LAN 等標準. 交換機(Switch)工作在數據鏈路層.
2.3 網絡層
負責地址管理和路由選擇. 例如在 IP 協議中, 通過 IP 地址來標識一臺主機, 并通過路由表的方式規劃出兩臺主機之間的數據傳輸的線路(路由). 路由器(Router)工作在網路層.
2.4 傳輸層
負責兩臺主機之間的數據傳輸. 如傳輸控制協議 (TCP), 能夠確保數據可靠的從源主機發送到目標主機.
2.5 應用層
負責應用程序間溝通,如簡單電子郵件傳輸(SMTP)、文件傳輸協議(FTP)、網絡遠程訪問協議(Telnet)等. 我們的網絡編程主要就是針對應用層.
OSI參考模型中,傳輸層的主要任務是向用戶提供可靠的端到端服務,透明地傳送報文,它向高層屏蔽了下層數據通信的細節,是計算機通信體系結構中最關鍵的一層。網絡層的主要任務是通過路由算法,為分組通過通信子網選擇最適當的路徑。數據鏈路層的主要任務是在鏈路上無差錯地傳送以幀(frame)為單位的數據。物理層的主要任務是把用戶的數據轉換為電信號,透明地傳送信號,是通信系統中最基本的掃描算法實現層。
3 TCP/IP協議族
所以,為什么要有 TCP/IP 協議?本質就是通信主機距離變遠了
3.1 什么是TCP/IP協議?
TCP/IP 協議的本質是一種解決方案
TCP/IP 協議能分層,前提是因為問題們本身能分層
3.1.1 OS與網絡關系
總結:網絡就是OS的一部分,TCP/IP網絡也是C語言寫的,不管什么OS網絡代碼和數據一定是一樣的,所謂的協議就是一個結構體
關于協議的樸素理解:所謂協議,就是通信雙方都認識的結構化的數據類型
因為協議棧是分層的,所以,每層都有雙方都有協議,同層之間,互相可以認識對方的協議。
4 網絡傳輸的基本流程
4.1 局域網
兩臺主機連接同一個局域網是能夠直接通信的
4.2 MAC地址
1、MAC 地址用來識別數據鏈路層中相連的節點;
2、長度為 48 位, 及 6 個字節. 一般用 16 進制數字加上冒號的形式來表示(例如:08:00:27:03:fb:19)
3、在網卡出廠時就確定了, 不能修改. mac 地址通常是唯一的(虛擬機中的 mac 地址不是真實的 mac 地址, 可能會沖突; 也有些網卡支持用戶配置 mac 地址).
命令:ifconfig,查看自己的MAC地址(linux)(ehth0)
局域網通信
將每一臺設備都看為一個網絡協議棧,主機A向主機E發送信息,實際上是向所有的設備都發送這條信息,然后經由數據鏈路層來判斷是否向本機發送的,如果不是直接忽略即可,所以對于上層的我們來說,我們根本不知道接沒接收到消息
在以太網中同一時刻只允許存在一份報文,因為如果有多臺設備互相發消息,可能會造成數據的污染,在這里以太網被視為臨界資源,我們需要互斥的訪問
1、以太網中,任何時刻,只允許一臺機器向網絡中發送數據
2、如果有多臺同時發送,會發生數據干擾,我們稱之為數據碰撞
3、所有發送數據的主機要進行碰撞檢測和碰撞避免
4、沒有交換機的情況下,一個以太網就是一個碰撞域
5、局域網通信的過程中,主機對收到的報文確認是否是發給自己的,是通過目標mac 地址判定
這里可以試著從系統角度來理解局域網通信原理
其中每層都有協議,所以當我進行進行上述傳輸流程的時候,要進行封裝和解包
每一層添加報頭的過程就是封裝的過程
問題:網卡(硬件)怎么知道有數據傳來?(中斷)
同層之間的通信我們可以視為直接通信。
整體復盤一下
從今天開始,我們學習任何協議,都要先宏觀上建立這樣的認識:
1.要學習的協議,是如何做到解包的?只有明確了解包,封包也就能理解
2.要學習的協議,是如何做到將自己的有效載荷,交付給上層協議的?
5 跨網絡傳輸
5.1 IP地址
IP 協議有兩個版本, IPv4 和 IPv6. 我們整個的課程, 凡是提到 IP 協議, 沒有特殊說明的,默認都是指 IPv4
?IP 地址是在 IP 協議中, 用來標識網絡中不同主機的地址;
?對于 IPv4 來說, IP 地址是一個 4 字節, 32 位的整數;
?我們通常也使用 “點分十進制” 的字符串表示 IP 地址, 例如 192.168.0.1 ; 用點分割的每一個數字表示一個字節, 范圍是 0 - 255;
ifconfig :查看linux機器的ip地址
Mac VS IP:
通信圖:
路由器是工作在網絡層的設備,在A和B看來路由器就是一臺主機,A和B也可以視為具有路由功能
在同一個路由器子網中,路由器會自動分配IP地址,同一個子網IP地址前綴一致
真實的網絡通信:
IP 網絡層存在的意義:提供網絡虛擬層,讓世界的所有網絡都是 IP 網絡,屏蔽最底層網絡的差異
6 Socket編程預備
6.1 源IP地址和目的IP地址
IP 在網絡中,用來標識主機的唯一性
數據傳輸到主機不是目的,而是手段。到達主機內部,在交給主機內的進程,才是目的。
6.2 端口號
端口號(port)是傳輸層協議的內容.
? 端口號是一個 2 字節 16 位的整數;
? 端口號用來標識一個進程, 告訴操作系統, 當前的這個數據要交給哪一個進程來處理;
? IP 地址 + 端口號能夠標識網絡上的某一臺主機的某一個進程;
? 一個端口號只能被一個進程占用.
IP地址標識特定主機,端口號標識特定進程
端口號范圍劃分
?0 - 1023: 知名端口號, HTTP, FTP, SSH 等這些廣為使用的應用層協議, 他們的端口號都是固定的.
?1024 - 65535: 操作系統動態分配的端口號. 客戶端程序的端口號, 就是由操作系統從這個范圍分配的.
7 傳統層的典型代表
如果我們了解了系統,也了解了網絡協議棧,我們就會清楚,傳輸層是屬于內核的,那么我們要通過網絡協議棧進行通信,必定調用的是傳輸層提供的系統調用,來進行的網絡通信。
8 了解協議
8.1 協議
認識 TCP 協議
此處我們先對 TCP(Transmission Control Protocol 傳輸控制協議)有一個直觀的認識;后面我們再詳細討論 TCP 的一些細節問題.
?傳輸層協議
?有連接
?可靠傳輸
?面向字節流
認識 UDP 協議
此處我們也是對 UDP(User Datagram Protocol 用戶數據報協議)有一個直觀的認識; 后
面再詳細討論.
?傳輸層協議
?無連接
?不可靠傳輸
?面向數據報
因為我們暫時還沒有深入了解 tcp、udp 協議,此處只做了解即可
8.2 網絡字節序
我們已經知道,內存中的多字節數據相對于內存地址有大端和小端之分, 磁盤文件中的多字節數據相對于文件中的偏移地址也有大端小端之分, 網絡數據流同樣有大端小端之分. 那么如何定義網絡數據流的地址呢?
?發送主機通常將發送緩沖區中的數據按內存地址從低到高的順序發出;
?接收主機把從網絡上接到的字節依次保存在接收緩沖區中,也是按內存地址從低到高的順序保存;
?因此,網絡數據流的地址應這樣規定:先發出的數據是低地址,后發出的數據是高地址.
?TCP/IP 協議規定,網絡數據流應采用大端字節序,即低地址高字節.
?不管這臺主機是大端機還是小端機, 都會按照這個 TCP/IP 規定的網絡字節序來發送/接收數據;
?如果當前發送主機是小端, 就需要先將數據轉成大端; 否則就忽略, 直接發送即可;
9 socket 編程接口
9.1 socket 常用API
// 創建 socket 文件描述符 (TCP/UDP, 客戶端 + 服務器)
int socket(int domain, int type, int protocol);
// 綁定端口號 (TCP/UDP, 服務器)
int bind(int socket, const struct sockaddr *address,
socklen_t address_len);
// 開始監聽 socket (TCP, 服務器)
int listen(int socket, int backlog);
// 接收請求 (TCP, 服務器)
int accept(int socket, struct sockaddr* address,
socklen_t* address_len);
// 建立連接 (TCP, 客戶端)
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
上面我們可以用多態和繼承來看待