每個程式設計師應該知道的計算機網路知識
前言
作為一名程式設計師, 不可能不與網路打交道. 現在我們的手機, 電腦, 不誇張地說, 離開了網路就是一塊’廢鐵’, 它們的作用將大打折扣.. 本文的作用呢, 主要是針對不是非網路專業開發的人員準備的, 以’最短的時間, 瞭解計網最多的知識’為前提起筆.
目錄
- 概述
- 物理層
- 資料鏈路層
- 網路層
- 傳輸層
- 應用層
概述
先來了解下各種我們知道, 但是不太瞭解的專業名詞的意思
因特網
因特網
因特網是當今世界上最大的網路, 是”網路的網路”. 即因特網是所有網路互連起來的一個巨型網路.
因特網的組成 :
- 邊緣部分 : 主機
- 核心部分 : 大量網路和連線這些網路的路由器(此路由器不是我們家用的路由器)
乙太網
乙太網是現在最常用的區域網通訊協議, 乙太網上傳輸的是MAC幀. 由於乙太網同一時間只允許一臺計算機傳送資料, 所以必須有一套檢測機制, 那就是CSMA/CD協議 :
- 多點接入 : 多臺計算機以多點接入的方式連線在一根匯流排上
- 載波監聽 : 不管是否正在傳送, 每個站都必須不停地檢測通道
- 碰撞檢測 : 邊傳送邊監聽
OSI
開放系統互連基本參考模型, 只要遵守這個OSI標準, 任何兩個系統都能進行通訊. OSI是七層協議體系結構, 而TCP/IP是一個四層協議體系結構, 於是我們採取折中的方法, 學習計算機網路原理的時候往往用的是五層協議的體系結構 : 物理層, 資料鏈路層, 網路層, 傳輸層和應用層
協議體系結構
物理層
計算機的世界裡只有0和1, 正如你現在所看這篇文章的文字, 儲存在計算機中也是一大串0和1的組合. 但是這些數字不能在真實的物理介質中傳輸的, 而需要把它轉換為光訊號或者電訊號, 所以這一層負責將這些位元流(0101)與光電訊號進行轉換.
如果沒有物理層, 那麼也就不存在網際網路, 不存在資料的共享, 因為資料無法在網路中流動.
資料鏈路層
資料在這一層不再是以位元流的形式傳輸, 而是分割成一個一個的幀再進行傳輸.
MAC地址
又稱計算機的硬體地址, 被固化在介面卡(網路卡)ROM上的佔48位的地址. MAC地址可以用來唯一區別一臺計算機, 因為它在全球是獨一無二的
分組交換
由於資料在這次曾要被分割成一個一個的幀, 由於不同的鏈路規定了不同的最大幀長, 即MTU(最大傳輸單元), 凡是超出這個MTU的幀都必須被分塊. 例如一臺貨車一次能運輸5噸的貨物, 而有條公路限載重2噸, 那麼你只好分3次運輸.
網橋
網橋工作在資料鏈路層, 根據MAC幀的目的地址對收到的幀進行轉發和過濾.
乙太網交換機
實際上就是一個多介面的網橋, 乙太網交換機的每個介面都直接與一個單個主機或另一個集線器相連, 可以很容易實現VLAN(虛擬區域網)
乙太網的MAC幀
MAC幀的格式為 :
MAC幀格式
- 目的地址 : 接收方48位的MAC地址
- 源地址 : 傳送方48位的MAC地址
- 型別欄位 : 標誌上一層使用的是什麼協議, 0×0800為IP資料包
網路層
如果只有資料鏈路層沒有網路層, 資料就只能在同一條鏈路上傳輸, 不能跨鏈路傳輸. 有了網路層, 資料便能跨域不同的資料鏈路傳輸.
IP地址
IP地址又稱為軟體地址, 儲存在計算機的儲存器上, IPv4地址為32位, IPv6地址為128位
IP地址和MAC地址
- 網路層以上使用IP地址, 資料鏈路層以下使用MAC地址
- IP地址是邏輯地址, MAC地址是實體地址
- IP分組中首部的源地址和目的地址在傳輸中不會改變, MAC幀中首部的源地址和目的地址每到一個路由器會改變一次
IP地址分類
IP地址 = {<網路號>, <主機號>}
A類地址 : 0.0.0.0 ~ 127.0.0.0
B類地址 : 128.0.0.0 ~ 191.255.0.0
C類地址 : 192.0.0.0 ~ 223.255.255.0
劃分子網之後的IP地址
IP地址 = {<網路號>, <子網號>, <主機號>}
例如某單位擁有一個B類IP地址, 145.13.0.0, 但凡目的地址為145.13.x.x的資料包都會被送到這個網路上的路由器R. 內部劃分子網後變成 : 145.13.3.0
, 145.13.7.0
, 145.13.21.0
. 但是對外仍表現為一個網路, 即145.13.0.0
. 這樣路由器R收到報文後, 再根據目的地址發到對應的子網上.
子網掩碼
一般由一串1和一串0組成, 不管網路有沒有劃分子網, 將子網掩碼和IP地址做按位與運算即可得出網路地址.
所有的網路都必須使用子網掩碼, 同時在路由表中必須有子網掩碼這一欄. 如果一個網路不劃分子網, 那麼該網路的子網掩碼就是預設的子網掩碼.
A類地址的預設子網掩碼為255.0.0.0
B類地址的預設子網掩碼為255.255.0.0
C類地址的預設子網掩碼為255.255.255.0
儘管劃分子網增加了靈活性, 但是卻減少了能夠連線在網路上的主機總數.
構成超網的IP地址
IP地址 = {<網路字首>, <主機號>}
使用網路字首, 無分類域間路由選擇CIDR
例如, 128.14.35.7/20, 意思是前20位為網路字首, 後12位為主機號. 另外, CIDR把網路字首相同的連續的IP地址組成一個”CIDR地址塊”
地址掩碼 : CIDR使用32位的地址掩碼, 類似於子網掩碼.
IP資料包
在網路層, 資料是以IP資料包(IP分組)的形式傳輸的
IP資料包的格式
首部前20位元組為固定長度, 是所有IP資料包必備的. 後4位元組是可選欄位, 其長度可變.
IP資料包首部固定的欄位分析 :
- 版本號 : IP協議的版本, IPv4或IPv6
- 首部長度 : 記錄了首部的長度, 最大為1111, 即15個32位字長, 即60位元組. 當首部長度不是4位元組的整數倍時, 需要使用最後的填充欄位加以填充.
- 服務型別 : 一般無用
- 總長度 : 指首部和資料之和的長度. 最大為216-1 = 65535位元組. 但是由於資料鏈路層規定每一幀的資料長度都有最大長度MTU, 乙太網規定MTU為1500位元組, 所以超出範圍的資料包就必須進行分片處理
- 標識 : 每產生一個IP資料包, 計數器就+1, 並將此值賦值給標識欄位. 再以後需要分片的資料包中, 標識相同說明是同一個資料包
- 標誌 : 佔3位, 最低位記為MF(More Fragment). MF = 1說明還有分片; MF = 0說明這已經是最後一個分片. 中間一位記為DF(Don’t Fragment), 意思是不能分片. 只有當DF = 0時才允許分片.
- 段位移 : 又稱片位移, 相對於使用者資料欄位的起點, 該片從何處開始. 片位移以8個位元組為偏移單位. 所以, 每個分片的長度一定是8位元組的整數倍.
- 生存時間 : TTL(Time To Live). 資料包能在因特網中經過路由器的最大次數為255次, 每經過一個路由器則TTL – 1, 為0時丟棄該報文.
- 協議 : 記錄該報文所攜帶的資料是使用何種協議.
- 首部檢驗和 : 只檢驗資料包的首部, 不檢驗資料部分. 不為0則丟棄報文.
- 源地址和目的地址 : 不解釋
IP層轉發分組的流程
每個路由器內部都維護一個路由表, 路由表包含以下內容(目的網路地址
, 下一跳地址
).
使用子網時分組轉發時, 路由表必須包含以下三項內容: 目的網路地址
, 子網掩碼
和下一跳地址
.
特定主機路由 : 對特定的目的地址指明一個路由
預設路由 : 不知道分組該發給哪個路由器時就發給預設路由. 當一個網路只有很少的對外連線時使用預設路由非常合適.
路由器的分組轉發演算法
- 從資料包中拿到目的IP地址D, 得出目的網路地址N
- 若N就是與此路由器直接相連的某個網路地址, 則直接交付(不需要再交給其他路由器轉發, 直接找到該目的主機交付), 否則 -> (3)
- 若路由表中有目的地址為D的特定主機路由, 則把資料包傳給該路由器, 否則 -> (4)
- 若路由表中有到達網路N的路由, 則把資料包傳給該路由器, 否則 -> (5)
- 若路由表中有預設路由, 則交給該路由器, 否則 -> (6)
- 報告轉發分組出錯
虛擬專用網VPN
因特網中的所有路由器對該目的地址是專用地址的資料包一律不轉發, 下面有3種專用地址(虛擬IP地址)
- 10.0.0.0 ~ 10.255.255.255
- 172.16.0.0 ~ 172.31.255.255
- 192.168.0.0 ~ 192.168.255.255
假設現在公司A有一個部門在廣州和另一個在上海, 而他們在當地都有自己的專用網. 那麼怎麼將這兩個專用網連線起來呢?
- 租用電信的通訊線路為本機構專用, 但是太貴了
- 利用公用的因特網當做通訊載體, 這就是虛擬專用網VPN
網路地址轉換NAT
多個專用網內部的主機公用一個NAT路由器的IP地址, 在主機傳送和接收IP資料包時必須先通過NAT路由器進行網路地址轉換.
NAT路由器的工作原理
不僅如此, NAT還能使用埠號, 搖身一變成為網路地址和埠轉換NAPT
ARP協議
ARP是解決同一個區域網上的主機或路由器的IP地址和MAC地址的對映問題, 即 IP地址 -> ARP -> MAC地址
每一個主機都有一個ARP快取記憶體, 裡面有本區域網上的各主機和路由器的IP地址到MAC地址的對映表. 以下是ARP的工作原理 :
ARP的工作原理.jpg
那如果是跨網路使用ARP呢?
- 在本網路上廣播
- 未找到該主機, 則到路由器
- 路由器幫忙轉發(在另一網路上廣播)
- 找到了則完成ARP請求, 未找到則返回(2)
傳輸層
這一層是重中之重, 因為資料鏈路層, 網路層這兩層的資料傳輸都是不可靠的, 盡最大能力交付的. 什麼意思的? 就是它們不負責提交給你的就是正確的資料. 然而這一層的TCP協議將要提供可靠傳輸
這一層主要重點是兩個協議 : UDP 和 TCP
使用者資料包協議UDP
UDP主要特點 :
- 無連線
- 盡最大努力交付
- 面向報文 : 應用層交下來的報文直接加上UDP頭部就往IP層扔, 不合並也不拆分
- 沒有擁塞控制
- 支援一對一, 一對多, 多對一和多對多的互動通訊
- 首部開銷小, 只有8個位元組
UDP首部
UDP首部格式
- 源埠 : 源埠號. 在需要對方回信時選用, 不需要則全0
- 目的埠 : 目的埠號. 這在終點交付報文時必須要使用到
- 長度 : UDP資料包的長度, 最小值為8(僅有首部)
- 檢驗和 : 與IP資料包只檢驗首部不同的是, UDP需要把首部和資料部分一起檢驗
傳輸控制協議TCP
TCP主要特點 :
- 面向連線的運輸層協議
- 每一條TCP連線只能有2個端點, TCP是點對點的
- 提供可靠交付
- 全雙工通訊
- 面向位元組流
TCP的工作流程
TCP位元組流
TCP的連線
TCP連線的端點叫套接字(socket)
socket = (IP地址 : 埠號)
每一條TCP連線唯一地被通訊兩端的兩個端點(socket)所確定. 即 :
TCP連線 ::= {socket1, socket2} = {(IP1 : port1), (IP2 : port2)}
TCP報文段的首部
TCP報文段的首部
- 源埠和目的埠 : 同UDP埠作用
- 序號 : 本報文段的資料的第一個位元組的序號
- 確認號 : 期望收到對方下一個報文段的第一個資料位元組的序號
若確認號 = N, 則表明 : 到序號N-1為止的所有資料都已正常收到
- 資料偏移 : TCP報文段的首部長度
- 保留 : 以後用, 目前為0
- 緊急URG : 若URG = 1時, 說明緊急指標欄位有效, 告訴系統這是緊急資料, 應儘快傳送. 例如突然要中斷傳送
- 確認ACK : ACK = 1時確認號才有效, ACK = 0時確認號無效. TCP規定, 連線建立後所有傳送的報文段都必須把ACK置1
- 推送PSH : 若PSH = 1, 則接收方收到報文段之後不再等到整個快取滿而是直接向上交付
- 復位RST : 當RST = 1, 說明TCP連線有嚴重錯誤, 必須釋放連線再重連
- 同步SYN : 在連線建立時用來同步序號. 當SYN = 1, ACK = 0時表明這是一個連線請求報文段, 對方若同意建立連線, 則在響應的報文段中置SYN = 1, ACK = 1
- 終止FIN : 當FIN = 1, 表明此報文段的傳送方資料已傳送完畢, 並要求釋放連線
- 視窗 : 告訴對方 : 從本報文段首部中的確認號算起, 接收方目前允許對方傳送的資料量. 這是作為接收方讓傳送方設定其傳送視窗的依據
- 檢驗和 : 同UDP, 檢驗首部和資料部分
- 緊急指標 : 當URG = 1時有效, 指出緊急資料的末尾在報文段的位置
- 選項 : 最大可40位元組, 沒有則為0
最大報文段長度MSS(Maximum Segment Size) : 每一個TCP報文段中資料欄位的最大長度, 若不填寫則為預設的536位元組.
視窗
TCP中很重要的一個概念, 那就是視窗(傳送視窗和接收視窗)
視窗
由於停止等待協議非常低效, 於是衍生出視窗這一概念. 上圖為傳送方維持的傳送視窗, 位於傳送視窗的5個分組都可以連續傳送出去而不需要等待對方的確認. 每收到一個確認, 就把傳送視窗前移一個分組的位置. 這大大提高了通道利用率!
接收方不必傳送每個分組的確認報文, 而是採用累積確認的方式. 也就是說, 對按序到達的最後一個分組傳送確認報文.
超時重傳
如果傳送方等待一段時間後, 還是沒收到 ACK 確認報文, 就會啟動超時重傳. 這個等待的時間為重傳超時時間(RTO, Retransmission TimeOut).
然而, RTO 的值不是固定的, 這個時間總是略大於連線往返時間(RTT,Round Trip Time). 假設報文傳送過去需要5秒, 對方收到後傳送確認報文回來也需要5秒, 那麼RTT就為10秒, 那這RTO就要比10秒要略大一些. 那麼超過RTO之後還沒有收到確認報文就認為報文丟失了, 就要重傳.
流量控制
利用滑動視窗和報文段的傳送時機來進行流量控制.
擁塞控制
傳送方維持一個擁塞視窗cwnd, 傳送視窗 = 擁塞視窗.
慢開始
: cwnd = 1, 然後每經過一個傳輸輪次就翻倍
擁塞避免
: 讓cwnd緩慢增大, 每經過一個傳輸輪次就+1
慢開始門限ssthresh
:
當cwnd < ssthresh, 使用慢開始演算法 當cwnd > ssthresh, 使用擁塞避免演算法 當cwnd = ssthresh, 隨意
擁塞控制
只要判斷網路出現擁塞, 把ssthresh設為當前傳送擁塞視窗的一半(不能小於2), 並把cwnd設為1, 重新執行慢開始演算法.
除了慢開始和擁塞避免演算法外, 還有一組快重傳和快恢復演算法 :
快重傳
: 接收方及時傳送確認, 而傳送方只要一連收到三個重複確認, 馬上重傳
快恢復
: 當傳送方一連收到三個重複確認時, ssthresh減半, cwnd設為ssthresh.
TCP三次握手
TCP三次握手建立連線和四次揮手斷開連線是面試愛問的知識點.
TCP三次握手
Q : 為什麼要三次握手, 兩次不可以嗎?
A : 試想一下, A第一次傳送請求連線, 但是在網路某節點滯留了, A超時重傳, 然後這一次一切正常, A跟B就愉快地進行資料傳輸了. 等到連線釋放了以後, 那個迷失了的連線請求突然到了B那, 如果是兩次握手的話, B傳送確認, 它們就算是建立起了連線了. 事實上A並不會理會這個確認, 因為我壓根沒有要傳資料啊. 但是B卻傻傻地以為有資料要來, 苦苦等待. 結果就是造成資源的浪費.
更加接地氣的解釋就是 : A打電話給B
第一次握手 : 你好, 我是A, 你能聽到我說話嗎 第二次握手 : 聽到了, 我是B, 你能聽到我說話嗎 第三次握手 : 聽到了, 我們可以開始聊天了 三次握手其實就是為了檢測雙方的傳送和接收能力是否正常, 你說呢?
TCP四次揮手
TCP四次揮手
Q : 為什麼要四次揮手, 而不是兩次, 三次?
A :
首先, 由於TCP的全雙工通訊, 雙方都能作為資料傳送方. A想要關閉連線, 必須要等資料都傳送完畢, 才傳送FIN給B. (此時A處於半關閉狀態)
然後, B傳送確認ACK, 並且B此時如果要傳送資料, 就傳送(例如做一些釋放前的處理)
再者, B傳送完資料之後, 傳送FIN給A. (此時B處於半關閉狀態)
然後, A傳送ACK, 進入TIME-WAIT狀態
最後, 經過2MSL時間後沒有收到B傳來的報文, 則確定B收到了ACK了. (此時A, B才算是處於完全關閉狀態)PS : 仔細分析以上步驟就知道為什麼不能少於四次揮手了.
Q : 為什麼要等待2MSL(Maximum Segment Lifetime)時間, 才從TIME_WAIT到CLOSED?
A : 在Client傳送出最後的ACK回覆,但該ACK可能丟失。Server如果沒有收到ACK,將不斷重複傳送FIN片段。所以Client不能立即關閉,它必須確認Server接收到了該ACK。Client會在傳送出ACK之後進入到TIME_WAIT狀態。Client會設定一個計時器,等待2MSL的時間。如果在該時間內再次收到FIN,那麼Client會重發ACK並再次等待2MSL。MSL指一個片段在網路中最大的存活時間,2MSL就是一個傳送和一個回覆所需的最大時間。如果直到2MSL,Client都沒有再次收到FIN,那麼Client推斷ACK已經被成功接收,則結束TCP連線。
更加接地氣的解釋 :
第一次揮手 : A告訴B, 我沒資料發了, 準備關閉連線了, 你要傳送資料嗎 第二次揮手 : B傳送最後的資料 第三次揮手 : B告訴A, 我也要關閉連線了 第四次揮手 : A告訴B你可以關閉了, 我這邊也關閉了
應用層
應用層協議最著名的就是HTTP, FTP了, 還有一個重要的DNS
域名系統(DNS, Domain Name System)
DNS 能將域名(例如, www.jianshu.com)解析成IP地址.
域名伺服器分類
- 根域名伺服器 : 最高層次的域名伺服器
- 頂級域名伺服器 : 如其名
- 許可權域名伺服器 : 負責一個區的應伺服器
- 本地域名伺服器 : 主機傳送DNS查詢請求就是發給它
DNS查詢
DNS查詢
- 主機向本地域名伺服器的查詢一般都是採用遞迴查詢
- 本地域名伺服器向根域名伺服器的查詢通常是採用迭代查詢
遞迴查詢 : B問A廣州怎麼去, A不知道, A就問C, C不知道就問D...直到知道了再一層一層轉告直到A告訴B. 迭代查詢 : B問A廣州怎麼去, A不知道, A就告訴你可以去問C, 然後B就去問C, C不知道, C就告訴你可以去問D, 然後B就去問D...直到B知道為止
DNS查詢例子 : 域名為x.tom.com的主機想知道y.jerry.com的IP地址
- 主機x.tom.com先向本地域名伺服器dns.tom.com進行遞迴查詢
- 本地域名伺服器採用迭代查詢. 它先問一個根域名伺服器
- 根域名伺服器告訴它, 你去問頂級域名伺服器dns.com
- 本地域名伺服器問頂級域名伺服器dns.com
- 頂級域名伺服器告訴它, 你去問許可權域名伺服器dns.jerry.com
- 本地域名伺服器問許可權域名伺服器dns.jerry.com
- 許可權域名伺服器dns.jerry.com告訴它所查詢的主機的IP地址
- 本地域名伺服器把查詢結果告訴主機x.tom.com
PS : 該查詢使用UDP, 並且為了提高DNS查詢效率, 每個域名伺服器都使用快取記憶體.
URL
URL的格式 : <協議>://<主機>:<埠>/<路徑>
, 埠和路徑有時可省略.
使用HTTP協議的URL : http://<主機>:<埠>/<路徑>
, HTTP預設埠號是80
HTTP協議
HTTP是面向事務的, 即它傳輸的資料是一個整體, 要麼全部收到, 要麼全部收不到.
全球資訊網的工作過程
每一次HTTP請求就需要建立一次TCP連線和釋放TCP連線.
HTTP是無連線, 無狀態的. 每一次請求都是作為一次新請求.
HTTP/1.0 缺點 : 無連線, 每一次請求都要重新建立TCP連線, 所以每一次HTTP請求都要花費2倍RTT時間(一次TCP請求, 一次HTTP請求)
HTTP/1.1 : 使用持續連線, 即保持TCP連線一段時間.
HTTP/1.1持續工作的兩種工作方式 : 非流水線方式和流水線方式 非流水線方式 : 收到一個請求的響應再發下一個請求, 效率低, 浪費資源 流水線方式 : 能夠同時傳送多個請求, 效率高
HTTP的GET和POST
GET 請求通常用於查詢、獲取資料,而 POST 請求則用於傳送資料
GET 請求的引數在URL中, 因此絕不能用GET請求傳輸敏感資料, 而POST 請求的引數在請求頭中, 安全性略高於GET請求
ps : POST請求的資料也是以明文的形式存放在請求頭中, 因此也不安全
Cookie
全球資訊網使用Cookie來跟蹤使用者, 表示HTTP伺服器和使用者之間傳遞的狀態資訊.
Cookie工作原理 :
1. 使用者瀏覽某網站, 該網站的伺服器為使用者產生一個唯一的識別碼, 並以此為索引在伺服器後端資料庫中產生一個專案 2. 返回給使用者的HTTP響應報文中新增一條 "Set-cookie", 值為該識別碼, 如123 3. 使用者的瀏覽器將該cookie儲存起來, 在用於繼續瀏覽該網站時傳送的每一個HTTP請求都會有一行 Cookie: 123 於是, 這個網站就知道Cookie為123的這個使用者做了什麼, 為這個使用者維護一個獨立的列表(如購物車)
當然, Cookie是把雙刃劍, 方便的同時也帶有危險性, 例如隱私洩露等, 使用者可以自行決定是否使用Cookie
Session
Cookie是儲存在客戶端上的, 而Session是儲存在伺服器中. 當伺服器收到使用者發出的Cookie時, 會根據Cookie中的SessionID來查詢對應的Session, 如沒有則會生成一個新的SessionID返回給使用者
總而言之, Cookie和Session就是同一樣東西存放地方不同而已.
HTTPS
HTTPS協議
HTTPS協議在HTTP協議的基礎上, 在HTTP和TCP中間加入了一層SSL/TLS加密層, 解決了HTTP不安全的問題: 冒充, 篡改, 竊聽三大風險.
對HTTPS是如何做到安全, 加密等有興趣的可以參考以下文章
相關文章
- 每個程式設計師應該知道12件事程式設計師
- 每個程式設計師應該知道的12個API程式設計師API
- 每個程式設計師都應該瞭解的硬體知識程式設計師
- 每個程式設計師都需要知道一些遊戲網路知識程式設計師遊戲
- 每個Android程式設計師應該知道的KotlinAndroid程式設計師Kotlin
- [翻譯]每一個計算機專業的學生應該知道的知識(一)計算機
- 每個程式設計師都應該瞭解的記憶體知識程式設計師記憶體
- 每個程式設計師都應該知道的 15 個最佳 PHP 庫程式設計師PHP
- 每個程式設計師都應該知道的基礎數論程式設計師
- 設計師都應該知道的ICON知識
- 每個程式設計師都應當知道的編譯器優化知識程式設計師編譯優化
- 為什麼每個程式設計師都應該懂點前端知識?程式設計師前端
- 程式設計師應該知道的 13 個設計技巧程式設計師
- 關於 Unicode 每個程式設計師應該知道的 5 件事Unicode程式設計師
- 每個程式設計師都應該瞭解的“虛擬記憶體”知識程式設計師記憶體
- 每個程式設計師都應該知道的下一個程式語言——Kotlin程式設計師Kotlin
- 每個程式設計師都應該讀的書程式設計師
- 每個程式設計師都該知道的編碼準則程式設計師
- 為SSD程式設計(6):總結—每個程式設計師都應該瞭解的固態硬碟知識程式設計師硬碟
- 每個Python新手都應該知道的程式設計技巧Python程式設計
- 為什麼每個程式設計師都應該學習程式碼編譯器知識程式設計師編譯
- 每個程式設計師都應該讀《Unix程式設計藝術》程式設計師
- 每個程式設計師都該知道的五大定律程式設計師
- 程式設計師應該是先是個計算機愛好者程式設計師計算機
- 程式設計師都應該知道的福利【必知必懂】程式設計師
- [譯] C程式設計師該知道的記憶體知識 (1)程式設計師記憶體
- [譯] C程式設計師該知道的記憶體知識 (4)程式設計師記憶體
- 每個程式設計師都應該成為架構師程式設計師架構
- 程式設計師都應該知道的福利程式設計師
- 國外程式設計師推薦:每個程式設計師都應該讀的非程式設計書程式設計師
- 程式設計師應該讀的 7 本計算機書程式設計師計算機
- Python 程式設計師應該知道的 10 個庫Python程式設計師
- 每個程式設計師都該知道的10大編碼原則程式設計師
- 計算機網路知識點計算機網路
- 計算機網路知識解析計算機網路
- Java程式設計師應該知道的20個有用的庫Java程式設計師
- 【計算機網路知識掃盲】03、計算機網路的功能(轉)計算機網路
- 【計算機網路知識掃盲】02、計算機網路的概念(轉)計算機網路