www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 公眾號(hào)精選 > CPP開發(fā)者
[導(dǎo)讀]↓推薦關(guān)注↓上篇:《重磅干貨|五萬字長文總結(jié)C/C知識(shí)(上)》網(wǎng)絡(luò)層IP(InternetProtocol,網(wǎng)際協(xié)議)是為計(jì)算機(jī)網(wǎng)絡(luò)相互連接進(jìn)行通信而設(shè)計(jì)的協(xié)議。ARP(AddressResolutionProtocol,地址解析協(xié)議)ICMP(InternetControlMe...


推薦關(guān)注↓



上篇:重磅干貨 | 五萬字長文總結(jié) C/C 知識(shí)(上)

網(wǎng)絡(luò)層

  • IP(Internet Protocol,網(wǎng)際協(xié)議)是為計(jì)算機(jī)網(wǎng)絡(luò)相互連接進(jìn)行通信而設(shè)計(jì)的協(xié)議。

  • ARP(Address Resolution Protocol,地址解析協(xié)議)

  • ICMP(Internet Control Message Protocol,網(wǎng)際控制報(bào)文協(xié)議)

  • IGMP(Internet Group Management Protocol,網(wǎng)際組管理協(xié)議)

IP 網(wǎng)際協(xié)議

IP 地址分類:

  • IP 地址 ::= {<網(wǎng)絡(luò)號(hào)>,<主機(jī)號(hào)>}


IP 地址類別網(wǎng)絡(luò)號(hào)網(wǎng)絡(luò)范圍主機(jī)號(hào)IP 地址范圍
A 類8bit,第一位固定為 00 —— 12724bit1.0.0.0 —— 127.255.255.255
B 類16bit,前兩位固定為 10128.0 —— 191.25516bit128.0.0.0 —— 191.255.255.255
C 類24bit,前三位固定為 110192.0.0 —— 223.255.2558bit192.0.0.0 —— 223.255.255.255
D 類前四位固定為 1110,后面為多播地址


E 類前五位固定為 11110,后面保留為今后所用


應(yīng)用:

  • PING(Packet InterNet Groper,分組網(wǎng)間探測(cè))測(cè)試兩個(gè)主機(jī)之間的連通性


      • TTL(Time To Live,生存時(shí)間)該字段指定 IP 包被路由器丟棄之前允許通過的最大網(wǎng)段數(shù)量

內(nèi)部網(wǎng)關(guān)協(xié)議

  • RIP(Routing Information Protocol,路由信息協(xié)議)

  • OSPF(Open Sortest Path First,開放最短路徑優(yōu)先)

外部網(wǎng)關(guān)協(xié)議

  • BGP(Border Gateway Protocol,邊界網(wǎng)關(guān)協(xié)議)

IP多播

  • IGMP(Internet Group Management Protocol,網(wǎng)際組管理協(xié)議)

  • 多播路由選擇協(xié)議

VPN 和 NAT

  • VPN(Virtual Private Network,虛擬專用網(wǎng))

  • NAT(Network Address Translation,網(wǎng)絡(luò)地址轉(zhuǎn)換)

路由表包含什么?

  1. 網(wǎng)絡(luò) ID(Network ID, Network number):就是目標(biāo)地址的網(wǎng)絡(luò) ID。

  2. 子網(wǎng)掩碼(subnet mask):用來判斷 IP 所屬網(wǎng)絡(luò)

  3. 下一跳地址/接口(Next hop / interface):就是數(shù)據(jù)在發(fā)送到目標(biāo)地址的旅途中下一站的地址。其中 interface 指向 next hop(即為下一個(gè) route)。一個(gè)自治系統(tǒng)(AS, Autonomous system)中的 route 應(yīng)該包含區(qū)域內(nèi)所有的子網(wǎng)絡(luò),而默認(rèn)網(wǎng)關(guān)(Network id:?0.0.0.0, Netmask:?0.0.0.0)指向自治系統(tǒng)的出口。

根據(jù)應(yīng)用和執(zhí)行的不同,路由表可能含有如下附加信息:

  1. 花費(fèi)(Cost):就是數(shù)據(jù)發(fā)送過程中通過路徑所需要的花費(fèi)。

  2. 路由的服務(wù)質(zhì)量

  3. 路由中需要過濾的出/入連接列表

運(yùn)輸層

協(xié)議:

  • TCP(Transmission Control Protocol,傳輸控制協(xié)議)

  • UDP(User Datagram Protocol,用戶數(shù)據(jù)報(bào)協(xié)議)

端口:

應(yīng)用程序FTPTELNETSMTPDNSTFTPHTTPHTTPSSNMP
端口號(hào)212325536980443161

受限于公眾號(hào)文章字?jǐn)?shù)限制,后續(xù)部分請(qǐng)看【今天的第二篇推文】,


TCP

  • TCP(Transmission Control Protocol,傳輸控制協(xié)議)是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議,其傳輸?shù)膯挝皇菆?bào)文段。

特征:

  • 面向連接

  • 只能點(diǎn)對(duì)點(diǎn)(一對(duì)一)通信

  • 可靠交互

  • 全雙工通信

  • 面向字節(jié)流

TCP 如何保證可靠傳輸:

  • 確認(rèn)和超時(shí)重傳

  • 數(shù)據(jù)合理分片和排序

  • 流量控制

  • 擁塞控制

  • 數(shù)據(jù)校驗(yàn)


TCP 首部

TCP:狀態(tài)控制碼(Code,Control Flag),占 6 比特,含義如下:

  • URG:緊急比特(urgent),當(dāng) URG=1 時(shí),表明緊急指針字段有效,代表該封包為緊急封包。它告訴系統(tǒng)此報(bào)文段中有緊急數(shù)據(jù),應(yīng)盡快傳送(相當(dāng)于高優(yōu)先級(jí)的數(shù)據(jù)), 且上圖中的 Urgent Pointer 字段也會(huì)被啟用。

  • ACK:確認(rèn)比特(Acknowledge)。只有當(dāng) ACK=1 時(shí)確認(rèn)號(hào)字段才有效,代表這個(gè)封包為確認(rèn)封包。當(dāng) ACK=0 時(shí),確認(rèn)號(hào)無效。

  • PSH:(Push function)若為 1 時(shí),代表要求對(duì)方立即傳送緩沖區(qū)內(nèi)的其他對(duì)應(yīng)封包,而無需等緩沖滿了才送。

  • RST:復(fù)位比特(Reset),當(dāng) RST=1 時(shí),表明 TCP 連接中出現(xiàn)嚴(yán)重差錯(cuò)(如由于主機(jī)崩潰或其他原因),必須釋放連接,然后再重新建立運(yùn)輸連接。

  • SYN:同步比特(Synchronous),SYN 置為 1,就表示這是一個(gè)連接請(qǐng)求或連接接受報(bào)文,通常帶有 SYN 標(biāo)志的封包表示『主動(dòng)』要連接到對(duì)方的意思。

  • FIN:終止比特(Final),用來釋放一個(gè)連接。當(dāng) FIN=1 時(shí),表明此報(bào)文段的發(fā)送端的數(shù)據(jù)已發(fā)送完畢,并要求釋放運(yùn)輸連接。

UDP

  • UDP(User Datagram Protocol,用戶數(shù)據(jù)報(bào)協(xié)議)是 OSI(Open System Interconnection 開放式系統(tǒng)互聯(lián)) 參考模型中一種無連接的傳輸層協(xié)議,提供面向事務(wù)的簡單不可靠信息傳送服務(wù),其傳輸?shù)膯挝皇怯脩魯?shù)據(jù)報(bào)。

特征:

  • 無連接

  • 盡最大努力交付

  • 面向報(bào)文

  • 沒有擁塞控制

  • 支持一對(duì)一、一對(duì)多、多對(duì)一、多對(duì)多的交互通信

  • 首部開銷小


TCP 與 UDP 的區(qū)別

  1. TCP 面向連接,UDP 是無連接的;

  2. TCP 提供可靠的服務(wù),也就是說,通過 TCP 連接傳送的數(shù)據(jù),無差錯(cuò),不丟失,不重復(fù),且按序到達(dá);UDP 盡最大努力交付,即不保證可靠交付

  3. TCP 的邏輯通信信道是全雙工的可靠信道;UDP 則是不可靠信道

  4. 每一條 TCP 連接只能是點(diǎn)到點(diǎn)的;UDP 支持一對(duì)一,一對(duì)多,多對(duì)一和多對(duì)多的交互通信

  5. TCP 面向字節(jié)流(可能出現(xiàn)黏包問題),實(shí)際上是 TCP 把數(shù)據(jù)看成一連串無結(jié)構(gòu)的字節(jié)流;UDP 是面向報(bào)文的(不會(huì)出現(xiàn)黏包問題)

  6. UDP 沒有擁塞控制,因此網(wǎng)絡(luò)出現(xiàn)擁塞不會(huì)使源主機(jī)的發(fā)送速率降低(對(duì)實(shí)時(shí)應(yīng)用很有用,如 IP 電話,實(shí)時(shí)視頻會(huì)議等)

  7. TCP 首部開銷20字節(jié);UDP 的首部開銷小,只有 8 個(gè)字節(jié)

TCP 黏包問題

原因
TCP 是一個(gè)基于字節(jié)流的傳輸服務(wù)(UDP 基于報(bào)文的),“流” 意味著 TCP 所傳輸?shù)臄?shù)據(jù)是沒有邊界的。所以可能會(huì)出現(xiàn)兩個(gè)數(shù)據(jù)包黏在一起的情況。

解決
  • 發(fā)送定長包。如果每個(gè)消息的大小都是一樣的,那么在接收對(duì)等方只要累計(jì)接收數(shù)據(jù),直到數(shù)據(jù)等于一個(gè)定長的數(shù)值就將它作為一個(gè)消息。

  • 包頭加上包體長度。包頭是定長的 4 個(gè)字節(jié),說明了包體的長度。接收對(duì)等方先接收包頭長度,依據(jù)包頭長度來接收包體。

  • 在數(shù)據(jù)包之間設(shè)置邊界,如添加特殊符號(hào) \r\n 標(biāo)記。FTP 協(xié)議正是這么做的。但問題在于如果數(shù)據(jù)正文中也含有 \r\n,則會(huì)誤判為消息的邊界。

  • 使用更加復(fù)雜的應(yīng)用層協(xié)議。

TCP 流量控制

概念
流量控制(flow control)就是讓發(fā)送方的發(fā)送速率不要太快,要讓接收方來得及接收。

方法

利用可變窗口進(jìn)行流量控制

TCP 擁塞控制

概念
擁塞控制就是防止過多的數(shù)據(jù)注入到網(wǎng)絡(luò)中,這樣可以使網(wǎng)絡(luò)中的路由器或鏈路不致過載。

方法
  • 慢開始( slow-start )

  • 擁塞避免( congestion avoidance )

  • 快重傳( fast retransmit )

  • 快恢復(fù)( fast recovery?


TCP 傳輸連接管理

因?yàn)?TCP 三次握手建立連接、四次揮手釋放連接很重要,所以附上《計(jì)算機(jī)網(wǎng)絡(luò)(第 7 版)-謝希仁》書中對(duì)此章的詳細(xì)描述:https://github.com/huihut/interview/blob/master/images/TCP-transport-connection-management.png

TCP 三次握手建立連接
UDP 報(bào)文
【TCP 建立連接全過程解釋】

  1. 客戶端發(fā)送 SYN 給服務(wù)器,說明客戶端請(qǐng)求建立連接;

  2. 服務(wù)端收到客戶端發(fā)的 SYN,并回復(fù) SYN ACK 給客戶端(同意建立連接);

  3. 客戶端收到服務(wù)端的 SYN ACK 后,回復(fù) ACK 給服務(wù)端(表示客戶端收到了服務(wù)端發(fā)的同意報(bào)文);

  4. 服務(wù)端收到客戶端的 ACK,連接已建立,可以數(shù)據(jù)傳輸。

TCP 為什么要進(jìn)行三次握手?
【答案一】因?yàn)樾诺啦豢煽浚?TCP 想在不可靠信道上建立可靠地傳輸,那么三次通信是理論上的最小值。(而 UDP 則不需建立可靠傳輸,因此 UDP 不需要三次握手。)

Google Groups . TCP 建立連接為什么是三次握手?{技術(shù)}{網(wǎng)絡(luò)通信}

【答案二】因?yàn)殡p方都需要確認(rèn)對(duì)方收到了自己發(fā)送的序列號(hào),確認(rèn)過程最少要進(jìn)行三次通信。

知乎 . TCP 為什么是三次握手,而不是兩次或四次?

【答案三】為了防止已失效的連接請(qǐng)求報(bào)文段突然又傳送到了服務(wù)端,因而產(chǎn)生錯(cuò)誤。

《計(jì)算機(jī)網(wǎng)絡(luò)(第 7 版)-謝希仁》


【TCP 釋放連接全過程解釋】

  1. 客戶端發(fā)送 FIN 給服務(wù)器,說明客戶端不必發(fā)送數(shù)據(jù)給服務(wù)器了(請(qǐng)求釋放從客戶端到服務(wù)器的連接);

  2. 服務(wù)器接收到客戶端發(fā)的 FIN,并回復(fù) ACK 給客戶端(同意釋放從客戶端到服務(wù)器的連接);

  3. 客戶端收到服務(wù)端回復(fù)的 ACK,此時(shí)從客戶端到服務(wù)器的連接已釋放(但服務(wù)端到客戶端的連接還未釋放,并且客戶端還可以接收數(shù)據(jù));

  4. 服務(wù)端繼續(xù)發(fā)送之前沒發(fā)完的數(shù)據(jù)給客戶端;

  5. 服務(wù)端發(fā)送 FIN ACK 給客戶端,說明服務(wù)端發(fā)送完了數(shù)據(jù)(請(qǐng)求釋放從服務(wù)端到客戶端的連接,就算沒收到客戶端的回復(fù),過段時(shí)間也會(huì)自動(dòng)釋放);

  6. 客戶端收到服務(wù)端的 FIN ACK,并回復(fù) ACK 給客戶端(同意釋放從服務(wù)端到客戶端的連接);

  7. 服務(wù)端收到客戶端的 ACK 后,釋放從服務(wù)端到客戶端的連接。

TCP 為什么要進(jìn)行四次揮手?
【問題一】TCP 為什么要進(jìn)行四次揮手?/ 為什么 TCP 建立連接需要三次,而釋放連接則需要四次?

【答案一】因?yàn)?TCP 是全雙工模式,客戶端請(qǐng)求關(guān)閉連接后,客戶端向服務(wù)端的連接關(guān)閉(一二次揮手),服務(wù)端繼續(xù)傳輸之前沒傳完的數(shù)據(jù)給客戶端(數(shù)據(jù)傳輸),服務(wù)端向客戶端的連接關(guān)閉(三四次揮手)。所以 TCP 釋放連接時(shí)服務(wù)器的 ACK 和 FIN 是分開發(fā)送的(中間隔著數(shù)據(jù)傳輸),而 TCP 建立連接時(shí)服務(wù)器的 ACK 和 SYN 是一起發(fā)送的(第二次握手),所以 TCP 建立連接需要三次,而釋放連接則需要四次。

【問題二】為什么 TCP 連接時(shí)可以 ACK 和 SYN 一起發(fā)送,而釋放時(shí)則 ACK 和 FIN 分開發(fā)送呢?(ACK 和 FIN 分開是指第二次和第三次揮手)

【答案二】因?yàn)榭蛻舳苏?qǐng)求釋放時(shí),服務(wù)器可能還有數(shù)據(jù)需要傳輸給客戶端,因此服務(wù)端要先響應(yīng)客戶端 FIN 請(qǐng)求(服務(wù)端發(fā)送 ACK),然后數(shù)據(jù)傳輸,傳輸完成后,服務(wù)端再提出 FIN 請(qǐng)求(服務(wù)端發(fā)送 FIN);而連接時(shí)則沒有中間的數(shù)據(jù)傳輸,因此連接時(shí)可以 ACK 和 SYN 一起發(fā)送。

【問題三】為什么客戶端釋放最后需要 TIME-WAIT 等待 2MSL 呢?

【答案三】

  1. 為了保證客戶端發(fā)送的最后一個(gè) ACK 報(bào)文能夠到達(dá)服務(wù)端。若未成功到達(dá),則服務(wù)端超時(shí)重傳 FIN ACK 報(bào)文段,客戶端再重傳 ACK,并重新計(jì)時(shí)。

  1. 防止已失效的連接請(qǐng)求報(bào)文段出現(xiàn)在本連接中。TIME-WAIT 持續(xù) 2MSL 可使本連接持續(xù)的時(shí)間內(nèi)所產(chǎn)生的所有報(bào)文段都從網(wǎng)絡(luò)中消失,這樣可使下次連接中不會(huì)出現(xiàn)舊的連接報(bào)文段。



應(yīng)用層

DNS

  • DNS(Domain Name System,域名系統(tǒng))是互聯(lián)網(wǎng)的一項(xiàng)服務(wù)。它作為將域名和 IP 地址相互映射的一個(gè)分布式數(shù)據(jù)庫,能夠使人更方便地訪問互聯(lián)網(wǎng)。DNS 使用 TCP 和 UDP 端口 53。當(dāng)前,對(duì)于每一級(jí)域名長度的限制是 63 個(gè)字符,域名總長度則不能超過 253 個(gè)字符。

域名:

  • 域名 ::= {<三級(jí)域名>.<二級(jí)域名>.<頂級(jí)域名>},如:blog.huihut.com

FTP

  • FTP(File Transfer Protocol,文件傳輸協(xié)議)是用于在網(wǎng)絡(luò)上進(jìn)行文件傳輸?shù)囊惶讟?biāo)準(zhǔn)協(xié)議,使用客戶/服務(wù)器模式,使用 TCP 數(shù)據(jù)報(bào),提供交互式訪問,雙向傳輸。

  • TFTP(Trivial File Transfer Protocol,簡單文件傳輸協(xié)議)一個(gè)小且易實(shí)現(xiàn)的文件傳輸協(xié)議,也使用客戶-服務(wù)器方式,使用UDP數(shù)據(jù)報(bào),只支持文件傳輸而不支持交互,沒有列目錄,不能對(duì)用戶進(jìn)行身份鑒定

TELNET

  • TELNET 協(xié)議是 TCP/IP 協(xié)議族中的一員,是 Internet 遠(yuǎn)程登陸服務(wù)的標(biāo)準(zhǔn)協(xié)議和主要方式。它為用戶提供了在本地計(jì)算機(jī)上完成遠(yuǎn)程主機(jī)工作的能力。

  • HTTP(HyperText Transfer Protocol,超文本傳輸協(xié)議)是用于從 WWW(World Wide Web,萬維網(wǎng))服務(wù)器傳輸超文本到本地瀏覽器的傳送協(xié)議。

  • SMTP(Simple Mail Transfer Protocol,簡單郵件傳輸協(xié)議)是一組用于由源地址到目的地址傳送郵件的規(guī)則,由它來控制信件的中轉(zhuǎn)方式。SMTP 協(xié)議屬于 TCP/IP 協(xié)議簇,它幫助每臺(tái)計(jì)算機(jī)在發(fā)送或中轉(zhuǎn)信件時(shí)找到下一個(gè)目的地。

  • Socket 建立網(wǎng)絡(luò)通信連接至少要一對(duì)端口號(hào)(Socket)。Socket 本質(zhì)是編程接口(API),對(duì) TCP/IP 的封裝,TCP/IP 也要提供可供程序員做網(wǎng)絡(luò)開發(fā)所用的接口,這就是 Socket 編程接口。

WWW

  • WWW(World Wide Web,環(huán)球信息網(wǎng),萬維網(wǎng))是一個(gè)由許多互相鏈接的超文本組成的系統(tǒng),通過互聯(lián)網(wǎng)訪問

URL
  • URL(Uniform Resource Locator,統(tǒng)一資源定位符)是因特網(wǎng)上標(biāo)準(zhǔn)的資源的地址(Address)

標(biāo)準(zhǔn)格式:

  • 協(xié)議類型:[//服務(wù)器地址[:端口號(hào)]][/資源層級(jí)UNIX文件路徑]文件名[?查詢][#片段ID]

完整格式:

  • 協(xié)議類型:[//[訪問資源需要的憑證信息@]服務(wù)器地址[:端口號(hào)]][/資源層級(jí)UNIX文件路徑]文件名[?查詢][#片段ID]

其中【訪問憑證信息@;:端口號(hào);?查詢;#片段ID】都屬于選填項(xiàng) ?
如:https://github.com/huihut/interview#cc

HTTP
HTTP(HyperText Transfer Protocol,超文本傳輸協(xié)議)是一種用于分布式、協(xié)作式和超媒體信息系統(tǒng)的應(yīng)用層協(xié)議。HTTP 是萬維網(wǎng)的數(shù)據(jù)通信的基礎(chǔ)。

請(qǐng)求方法

方法意義
OPTIONS請(qǐng)求一些選項(xiàng)信息,允許客戶端查看服務(wù)器的性能
GET請(qǐng)求指定的頁面信息,并返回實(shí)體主體
HEAD類似于 get 請(qǐng)求,只不過返回的響應(yīng)中沒有具體的內(nèi)容,用于獲取報(bào)頭
POST向指定資源提交數(shù)據(jù)進(jìn)行處理請(qǐng)求(例如提交表單或者上傳文件)。數(shù)據(jù)被包含在請(qǐng)求體中。POST請(qǐng)求可能會(huì)導(dǎo)致新的資源的建立和/或已有資源的修改
PUT從客戶端向服務(wù)器傳送的數(shù)據(jù)取代指定的文檔的內(nèi)容
DELETE請(qǐng)求服務(wù)器刪除指定的頁面
TRACE回顯服務(wù)器收到的請(qǐng)求,主要用于測(cè)試或診斷
狀態(tài)碼(Status-Code)

  • 1xx:表示通知信息,如請(qǐng)求收到了或正在進(jìn)行處理

    • 100 Continue:繼續(xù),客戶端應(yīng)繼續(xù)其請(qǐng)求

    • 101 Switching Protocols 切換協(xié)議。服務(wù)器根據(jù)客戶端的請(qǐng)求切換協(xié)議。只能切換到更高級(jí)的協(xié)議,例如,切換到 HTTP 的新版本協(xié)議

  • 2xx:表示成功,如接收或知道了

    • 200 OK: 請(qǐng)求成功

  • 3xx:表示重定向,如要完成請(qǐng)求還必須采取進(jìn)一步的行動(dòng)

    • 301 Moved Permanently: 永久移動(dòng)。請(qǐng)求的資源已被永久的移動(dòng)到新 URL,返回信息會(huì)包括新的 URL,瀏覽器會(huì)自動(dòng)定向到新 URL。今后任何新的請(qǐng)求都應(yīng)使用新的 URL 代替

  • 4xx:表示客戶的差錯(cuò),如請(qǐng)求中有錯(cuò)誤的語法或不能完成

    • 400 Bad Request: 客戶端請(qǐng)求的語法錯(cuò)誤,服務(wù)器無法理解

    • 401 Unauthorized: 請(qǐng)求要求用戶的身份認(rèn)證

    • 403 Forbidden: 服務(wù)器理解請(qǐng)求客戶端的請(qǐng)求,但是拒絕執(zhí)行此請(qǐng)求(權(quán)限不夠)

    • 404 Not Found: 服務(wù)器無法根據(jù)客戶端的請(qǐng)求找到資源(網(wǎng)頁)。通過此代碼,網(wǎng)站設(shè)計(jì)人員可設(shè)置 “您所請(qǐng)求的資源無法找到” 的個(gè)性頁面

    • 408 Request Timeout: 服務(wù)器等待客戶端發(fā)送的請(qǐng)求時(shí)間過長,超時(shí)

  • 5xx:表示服務(wù)器的差錯(cuò),如服務(wù)器失效無法完成請(qǐng)求

    • 500 Internal Server Error: 服務(wù)器內(nèi)部錯(cuò)誤,無法完成請(qǐng)求

    • 503 Service Unavailable: 由于超載或系統(tǒng)維護(hù),服務(wù)器暫時(shí)的無法處理客戶端的請(qǐng)求。延時(shí)的長度可包含在服務(wù)器的 Retry-After 頭信息中

    • 504 Gateway Timeout: 充當(dāng)網(wǎng)關(guān)或代理的服務(wù)器,未及時(shí)從遠(yuǎn)端服務(wù)器獲取請(qǐng)求

更多狀態(tài)碼:菜鳥教程 . HTTP狀態(tài)碼

其他協(xié)議
  • SMTP(Simple Main Transfer Protocol,簡單郵件傳輸協(xié)議)是在 Internet 傳輸 Email 的標(biāo)準(zhǔn),是一個(gè)相對(duì)簡單的基于文本的協(xié)議。在其之上指定了一條消息的一個(gè)或多個(gè)接收者(在大多數(shù)情況下被確認(rèn)是存在的),然后消息文本會(huì)被傳輸。可以很簡單地通過 Telnet 程序來測(cè)試一個(gè) SMTP 服務(wù)器。SMTP 使用 TCP 端口 25。

  • DHCP(Dynamic Host Configuration Protocol,動(dòng)態(tài)主機(jī)設(shè)置協(xié)議)是一個(gè)局域網(wǎng)的網(wǎng)絡(luò)協(xié)議,使用 UDP 協(xié)議工作,主要有兩個(gè)用途:

    • 用于內(nèi)部網(wǎng)絡(luò)或網(wǎng)絡(luò)服務(wù)供應(yīng)商自動(dòng)分配 IP 地址給用戶

    • 用于內(nèi)部網(wǎng)絡(luò)管理員作為對(duì)所有電腦作中央管理的手段

  • SNMP(Simple Network Management Protocol,簡單網(wǎng)絡(luò)管理協(xié)議)構(gòu)成了互聯(lián)網(wǎng)工程工作小組(IETF,Internet Engineering Task Force)定義的 Internet 協(xié)議族的一部分。該協(xié)議能夠支持網(wǎng)絡(luò)管理系統(tǒng),用以監(jiān)測(cè)連接到網(wǎng)絡(luò)上的設(shè)備是否有任何引起管理上關(guān)注的情況。

網(wǎng)絡(luò)編程

Socket

Socket 中的 read()、write() 函數(shù)

ssize_t?read(int?fd,?void?*buf,?size_t?count);
ssize_t?write(int?fd,?const?void?*buf,?size_t?count);
read()
  • read 函數(shù)是負(fù)責(zé)從 fd 中讀取內(nèi)容。

  • 當(dāng)讀成功時(shí),read 返回實(shí)際所讀的字節(jié)數(shù)。

  • 如果返回的值是 0 表示已經(jīng)讀到文件的結(jié)束了,小于 0 表示出現(xiàn)了錯(cuò)誤。

  • 如果錯(cuò)誤為 EINTR 說明讀是由中斷引起的;如果是 ECONNREST 表示網(wǎng)絡(luò)連接出了問題。

write()
  • write 函數(shù)將 buf 中的 nbytes 字節(jié)內(nèi)容寫入文件描述符 fd。

  • 成功時(shí)返回寫的字節(jié)數(shù)。失敗時(shí)返回 -1,并設(shè)置 errno 變量。

  • 在網(wǎng)絡(luò)程序中,當(dāng)我們向套接字文件描述符寫時(shí)有倆種可能。

  • (1)write 的返回值大于 0,表示寫了部分或者是全部的數(shù)據(jù)。

  • (2)返回的值小于 0,此時(shí)出現(xiàn)了錯(cuò)誤。

  • 如果錯(cuò)誤為 EINTR 表示在寫的時(shí)候出現(xiàn)了中斷錯(cuò)誤;如果為 EPIPE 表示網(wǎng)絡(luò)連接出現(xiàn)了問題(對(duì)方已經(jīng)關(guān)閉了連接)。

Socket 中 TCP 的三次握手建立連接

我們知道 TCP 建立連接要進(jìn)行 “三次握手”,即交換三個(gè)分組。大致流程如下:

  1. 客戶端向服務(wù)器發(fā)送一個(gè) SYN J

  2. 服務(wù)器向客戶端響應(yīng)一個(gè) SYN K,并對(duì) SYN J 進(jìn)行確認(rèn) ACK J 1

  3. 客戶端再想服務(wù)器發(fā)一個(gè)確認(rèn) ACK K 1

只有就完了三次握手,但是這個(gè)三次握手發(fā)生在 Socket 的那幾個(gè)函數(shù)中呢?請(qǐng)看下圖:

socket 中發(fā)送的 TCP 三次握手
從圖中可以看出:

  1. 當(dāng)客戶端調(diào)用 connect 時(shí),觸發(fā)了連接請(qǐng)求,向服務(wù)器發(fā)送了 SYN J 包,這時(shí) connect 進(jìn)入阻塞狀態(tài);?

  2. 服務(wù)器監(jiān)聽到連接請(qǐng)求,即收到 SYN J 包,調(diào)用 accept 函數(shù)接收請(qǐng)求向客戶端發(fā)送 SYN K ,ACK J 1,這時(shí) accept 進(jìn)入阻塞狀態(tài);?

  3. 客戶端收到服務(wù)器的 SYN K ,ACK J 1 之后,這時(shí) connect 返回,并對(duì) SYN K 進(jìn)行確認(rèn);?

  4. 服務(wù)器收到 ACK K 1 時(shí),accept 返回,至此三次握手完畢,連接建立。

Socket 中 TCP 的四次握手釋放連接

上面介紹了 socket 中 TCP 的三次握手建立過程,及其涉及的 socket 函數(shù)?,F(xiàn)在我們介紹 socket 中的四次握手釋放連接的過程,請(qǐng)看下圖:

socket 中發(fā)送的 TCP 四次握手
圖示過程如下:

  1. 某個(gè)應(yīng)用進(jìn)程首先調(diào)用 close 主動(dòng)關(guān)閉連接,這時(shí) TCP 發(fā)送一個(gè) FIN M;

  2. 另一端接收到 FIN M 之后,執(zhí)行被動(dòng)關(guān)閉,對(duì)這個(gè) FIN 進(jìn)行確認(rèn)。它的接收也作為文件結(jié)束符傳遞給應(yīng)用進(jìn)程,因?yàn)?FIN 的接收意味著應(yīng)用進(jìn)程在相應(yīng)的連接上再也接收不到額外數(shù)據(jù);

  3. 一段時(shí)間之后,接收到文件結(jié)束符的應(yīng)用進(jìn)程調(diào)用 close 關(guān)閉它的 socket。這導(dǎo)致它的 TCP 也發(fā)送一個(gè) FIN N;

  4. 接收到這個(gè) FIN 的源發(fā)送端 TCP 對(duì)它進(jìn)行確認(rèn)。

這樣每個(gè)方向上都有一個(gè) FIN 和 ACK。

數(shù)據(jù)庫

  • 數(shù)據(jù)庫事務(wù)四大特性:原子性、一致性、分離性、持久性

  • 數(shù)據(jù)庫索引:順序索引、B 樹索引、hash 索引
    MySQL 索引背后的數(shù)據(jù)結(jié)構(gòu)及算法原理

  • SQL 約束 (Constraints)

范式

  • 第一范式(1NF):屬性(字段)是最小單位不可再分

  • 第二范式(2NF):滿足 1NF,每個(gè)非主屬性完全依賴于主鍵(消除 1NF 非主屬性對(duì)碼的部分函數(shù)依賴)

  • 第三范式(3NF):滿足 2NF,任何非主屬性不依賴于其他非主屬性(消除 2NF 主屬性對(duì)碼的傳遞函數(shù)依賴)

  • 鮑依斯-科得范式(BCNF):滿足 3NF,任何非主屬性不能對(duì)主鍵子集依賴(消除 3NF 主屬性對(duì)碼的部分和傳遞函數(shù)依賴)

  • 第四范式(4NF):滿足 3NF,屬性之間不能有非平凡且非函數(shù)依賴的多值依賴(消除 3NF 非平凡且非函數(shù)依賴的多值依賴)

設(shè)計(jì)模式

各大設(shè)計(jì)模式例子參考:CSDN專欄 . C 設(shè)計(jì)模式 系列博文

設(shè)計(jì)模式工程目錄

單例模式

單例模式例子

抽象工廠模式

抽象工廠模式例子

適配器模式

適配器模式例子

橋接模式

橋接模式例子

觀察者模式

觀察者模式例子

設(shè)計(jì)模式的六大原則

  • 單一職責(zé)原則(SRP,Single Responsibility Principle)

  • 里氏替換原則(LSP,Liskov Substitution Principle)

  • 依賴倒置原則(DIP,Dependence Inversion Principle)

  • 接口隔離原則(ISP,Interface Segregation Principle)

  • 迪米特法則(LoD,Law of Demeter)

  • 開放封閉原則(OCP,Open Close Principle)

鏈接裝載庫

內(nèi)存、棧、堆

一般應(yīng)用程序內(nèi)存空間有如下區(qū)域:

  • 棧:由操作系統(tǒng)自動(dòng)分配釋放,存放函數(shù)的參數(shù)值、局部變量等的值,用于維護(hù)函數(shù)調(diào)用的上下文

  • 堆:一般由程序員分配釋放,若程序員不釋放,程序結(jié)束時(shí)可能由操作系統(tǒng)回收,用來容納應(yīng)用程序動(dòng)態(tài)分配的內(nèi)存區(qū)域

  • 可執(zhí)行文件映像:存儲(chǔ)著可執(zhí)行文件在內(nèi)存中的映像,由裝載器裝載是將可執(zhí)行文件的內(nèi)存讀取或映射到這里

  • 保留區(qū):保留區(qū)并不是一個(gè)單一的內(nèi)存區(qū)域,而是對(duì)內(nèi)存中受到保護(hù)而禁止訪問的內(nèi)存區(qū)域的總稱,如通常 C 語言講無效指針賦值為 0(NULL),因此 0 地址正常情況下不可能有效的訪問數(shù)據(jù)

棧保存了一個(gè)函數(shù)調(diào)用所需要的維護(hù)信息,常被稱為堆棧幀(Stack Frame)或活動(dòng)記錄(Activate Record),一般包含以下幾方面:

  • 函數(shù)的返回地址和參數(shù)

  • 臨時(shí)變量:包括函數(shù)的非靜態(tài)局部變量以及編譯器自動(dòng)生成的其他臨時(shí)變量

  • 保存上下文:包括函數(shù)調(diào)用前后需要保持不變的寄存器

堆分配算法:

  • 空閑鏈表(Free List)

  • 位圖(Bitmap)

  • 對(duì)象池

“段錯(cuò)誤(segment fault)” 或 “非法操作,該內(nèi)存地址不能 read/write”

典型的非法指針解引用造成的錯(cuò)誤。當(dāng)指針指向一個(gè)不允許讀寫的內(nèi)存地址,而程序卻試圖利用指針來讀或?qū)懺摰刂窌r(shí),會(huì)出現(xiàn)這個(gè)錯(cuò)誤。

普遍原因:

  • 將指針初始化為 NULL,之后沒有給它一個(gè)合理的值就開始使用指針

  • 沒用初始化棧中的指針,指針的值一般會(huì)是隨機(jī)數(shù),之后就直接開始使用指針

編譯鏈接

各平臺(tái)文件格式

平臺(tái)可執(zhí)行文件目標(biāo)文件動(dòng)態(tài)庫/共享對(duì)象靜態(tài)庫
Windowsexeobjdlllib
Unix/LinuxELF、outosoa
MacMach-Oodylib、tbd、frameworka、framework

編譯鏈接過程

  1. 預(yù)編譯(預(yù)編譯器處理如 #include、#define 等預(yù)編譯指令,生成 .i.ii 文件)

  2. 編譯(編譯器進(jìn)行詞法分析、語法分析、語義分析、中間代碼生成、目標(biāo)代碼生成、優(yōu)化,生成 .s 文件)

  3. 匯編(匯編器把匯編碼翻譯成機(jī)器碼,生成 .o 文件)

  4. 鏈接(連接器進(jìn)行地址和空間分配、符號(hào)決議、重定位,生成 .out 文件)

現(xiàn)在版本 GCC 把預(yù)編譯和編譯合成一步,預(yù)編譯編譯程序 cc1、匯編器 as、連接器 ld

MSVC 編譯環(huán)境,編譯器 cl、連接器 link、可執(zhí)行文件查看器 dumpbin

目標(biāo)文件

編譯器編譯源代碼后生成的文件叫做目標(biāo)文件。目標(biāo)文件從結(jié)構(gòu)上講,它是已經(jīng)編譯后的可執(zhí)行文件格式,只是還沒有經(jīng)過鏈接的過程,其中可能有些符號(hào)或有些地址還沒有被調(diào)整。

可執(zhí)行文件(Windows 的 .exe 和 Linux 的 ELF)、動(dòng)態(tài)鏈接庫(Windows 的 .dll 和 Linux 的 .so)、靜態(tài)鏈接庫(Windows 的 .lib 和 Linux 的 .a)都是按照可執(zhí)行文件格式存儲(chǔ)(Windows 按照 PE-COFF,Linux 按照 ELF)

目標(biāo)文件格式
  • Windows 的 PE(Portable Executable),或稱為 PE-COFF,.obj 格式

  • Linux 的 ELF(Executable Linkable Format),.o 格式

  • Intel/Microsoft 的 OMF(Object Module Format)

  • Unix 的 a.out 格式

  • MS-DOS 的 .COM 格式

PE 和 ELF 都是 COFF(Common File Format)的變種

目標(biāo)文件存儲(chǔ)結(jié)構(gòu)
功能
File Header文件頭,描述整個(gè)文件的文件屬性(包括文件是否可執(zhí)行、是靜態(tài)鏈接或動(dòng)態(tài)連接及入口地址、目標(biāo)硬件、目標(biāo)操作系統(tǒng)等)
.text section代碼段,執(zhí)行語句編譯成的機(jī)器代碼
.data section數(shù)據(jù)段,已初始化的全局變量和局部靜態(tài)變量
.bss sectionBSS 段(Block Started by Symbol),未初始化的全局變量和局部靜態(tài)變量(因?yàn)槟J(rèn)值為 0,所以只是在此預(yù)留位置,不占空間)
.rodata section只讀數(shù)據(jù)段,存放只讀數(shù)據(jù),一般是程序里面的只讀變量(如 const 修飾的變量)和字符串常量
.comment section注釋信息段,存放編譯器版本信息
.note.GNU-stack section堆棧提示段

其他段略

鏈接的接口————符號(hào)

在鏈接中,目標(biāo)文件之間相互拼合實(shí)際上是目標(biāo)文件之間對(duì)地址的引用,即對(duì)函數(shù)和變量的地址的引用。我們將函數(shù)和變量統(tǒng)稱為符號(hào)(Symbol),函數(shù)名或變量名就是符號(hào)名(Symbol Name)。

如下符號(hào)表(Symbol Table):

Symbol(符號(hào)名)Symbol Value (地址)
main0x100
Add0x123
......

Linux 的共享庫(Shared Library)

Linux 下的共享庫就是普通的 ELF 共享對(duì)象。

共享庫版本更新應(yīng)該保證二進(jìn)制接口 ABI(Application Binary Interface)的兼容

命名

libname.so.x.y.z

  • x:主版本號(hào),不同主版本號(hào)的庫之間不兼容,需要重新編譯

  • y:次版本號(hào),高版本號(hào)向后兼容低版本號(hào)

  • z:發(fā)布版本號(hào),不對(duì)接口進(jìn)行更改,完全兼容

路徑

大部分包括 Linux 在內(nèi)的開源系統(tǒng)遵循 FHS(File Hierarchy Standard)的標(biāo)準(zhǔn),這標(biāo)準(zhǔn)規(guī)定了系統(tǒng)文件如何存放,包括各個(gè)目錄結(jié)構(gòu)、組織和作用。

  • /lib:存放系統(tǒng)最關(guān)鍵和最基礎(chǔ)的共享庫,如動(dòng)態(tài)鏈接器、C 語言運(yùn)行庫、數(shù)學(xué)庫等

  • /usr/lib:存放非系統(tǒng)運(yùn)行時(shí)所需要的關(guān)鍵性的庫,主要是開發(fā)庫

  • /usr/local/lib:存放跟操作系統(tǒng)本身并不十分相關(guān)的庫,主要是一些第三方應(yīng)用程序的庫

動(dòng)態(tài)鏈接器會(huì)在 /lib、/usr/lib 和由 /etc/ld.so.conf 配置文件指定的,目錄中查找共享庫

環(huán)境變量

  • LD_LIBRARY_PATH:臨時(shí)改變某個(gè)應(yīng)用程序的共享庫查找路徑,而不會(huì)影響其他應(yīng)用程序

  • LD_PRELOAD:指定預(yù)先裝載的一些共享庫甚至是目標(biāo)文件

  • LD_DEBUG:打開動(dòng)態(tài)鏈接器的調(diào)試功能

so 共享庫的編寫

使用 CLion 編寫共享庫

創(chuàng)建一個(gè)名為 MySharedLib 的共享庫

CMakeLists.txt

cmake_minimum_required(VERSION?3.10)
project(MySharedLib)

set(CMAKE_CXX_STANDARD?11)

add_library(MySharedLib?SHARED?library.cpp?library.h)
library.h

#ifndef?MYSHAREDLIB_LIBRARY_H
#define?MYSHAREDLIB_LIBRARY_H

//?打印?Hello?World!
void?hello();

//?使用可變模版參數(shù)求和
template?<typename?T>
T?sum(T?t)
{
????return?t;
}
template?<typename?T,?typename?...Types>
T?sum(T?first,?Types?...?rest)
{
????return?first? ?sum(rest...);
}

#endif
library.cpp

#include?
#include?"library.h"

void?hello()?{
????std::cout?<"Hello,?World!"?<std::endl;
}

so 共享庫的使用(被可執(zhí)行項(xiàng)目調(diào)用)

使用 CLion 調(diào)用共享庫

創(chuàng)建一個(gè)名為 TestSharedLib 的可執(zhí)行項(xiàng)目

CMakeLists.txt

cmake_minimum_required(VERSION?3.10)
project(TestSharedLib)

#?C 11?編譯
set(CMAKE_CXX_STANDARD?11)

#?頭文件路徑
set(INC_DIR?/home/xx/code/clion/MySharedLib)
#?庫文件路徑
set(LIB_DIR?/home/xx/code/clion/MySharedLib/cmake-build-debug)

include_directories(${INC_DIR})
link_directories(${LIB_DIR})
link_libraries(MySharedLib)

add_executable(TestSharedLib?main.cpp)

#?鏈接?MySharedLib?庫
target_link_libraries(TestSharedLib?MySharedLib)
main.cpp

#include?
#include?"library.h"
using?std::cout;
using?std::endl;

int?main()?{

????hello();
????cout?<"1? ?2?=?"?<1,2)?<endl;
????cout?<"1? ?2? ?3?=?"?<1,2,3)?<endl;

????return?0;
}
執(zhí)行結(jié)果

Hello,?World!
1? ?2?=?3
1? ?2? ?3?=?6

Windows 應(yīng)用程序入口函數(shù)

  • GUI(Graphical User Interface)應(yīng)用,鏈接器選項(xiàng):/SUBSYSTEM:WINDOWS

  • CUI(Console User Interface)應(yīng)用,鏈接器選項(xiàng):/SUBSYSTEM:CONSOLE

_tWinMain 與 _tmain 函數(shù)聲明

Int?WINAPI?_tWinMain(
????HINSTANCE?hInstanceExe,
????HINSTANCE,
????PTSTR?pszCmdLine,
????int?nCmdShow);

int?_tmain(
????int?argc,
????TCHAR?*argv[],
????TCHAR?*envp[]);


應(yīng)用程序類型入口點(diǎn)函數(shù)嵌入可執(zhí)行文件的啟動(dòng)函數(shù)
處理ANSI字符(串)的GUI應(yīng)用程序_tWinMain(WinMain)WinMainCRTSartup
處理Unicode字符(串)的GUI應(yīng)用程序_tWinMain(wWinMain)wWinMainCRTSartup
處理ANSI字符(串)的CUI應(yīng)用程序_tmain(Main)mainCRTSartup
處理Unicode字符(串)的CUI應(yīng)用程序_tmain(wMain)wmainCRTSartup
動(dòng)態(tài)鏈接庫(Dynamic-Link Library)DllMain_DllMainCRTStartup

Windows 的動(dòng)態(tài)鏈接庫(Dynamic-Link Library)

知識(shí)點(diǎn)來自《Windows核心編程(第五版)》

用處

  • 擴(kuò)展了應(yīng)用程序的特性

  • 簡化了項(xiàng)目管理

  • 有助于節(jié)省內(nèi)存

  • 促進(jìn)了資源的共享

  • 促進(jìn)了本地化

  • 有助于解決平臺(tái)間的差異

  • 可以用于特殊目的

注意

  • 創(chuàng)建 DLL,事實(shí)上是在創(chuàng)建可供一個(gè)可執(zhí)行模塊調(diào)用的函數(shù)

  • 當(dāng)一個(gè)模塊提供一個(gè)內(nèi)存分配函數(shù)(malloc、new)的時(shí)候,它必須同時(shí)提供另一個(gè)內(nèi)存釋放函數(shù)(free、delete)

  • 在使用 C 和 C 混編的時(shí)候,要使用 extern "C" 修飾符

  • 一個(gè) DLL 可以導(dǎo)出函數(shù)、變量(避免導(dǎo)出)、C 類(導(dǎo)出導(dǎo)入需要同編譯器,否則避免導(dǎo)出)

  • DLL 模塊:cpp 文件中的 __declspec(dllexport) 寫在 include 頭文件之前

  • 調(diào)用 DLL 的可執(zhí)行模塊:cpp 文件的 __declspec(dllimport) 之前不應(yīng)該定義 MYLIBAPI

加載 Windows 程序的搜索順序

  1. 包含可執(zhí)行文件的目錄

  2. Windows 的系統(tǒng)目錄,可以通過 GetSystemDirectory 得到

  3. 16 位的系統(tǒng)目錄,即 Windows 目錄中的 System 子目錄

  4. Windows 目錄,可以通過 GetWindowsDirectory 得到

  5. 進(jìn)程的當(dāng)前目錄

  6. PATH 環(huán)境變量中所列出的目錄

DLL 入口函數(shù)

DllMain 函數(shù)

BOOL?WINAPI?DllMain(HINSTANCE?hinstDLL,?DWORD?fdwReason,?LPVOID?lpvReserved)
{
????switch(fdwReason)
????{
????case?DLL_PROCESS_ATTACH:
????????//?第一次將一個(gè)DLL映射到進(jìn)程地址空間時(shí)調(diào)用
????????//?The?DLL?is?being?mapped?into?the?process'?address?space.
????????break;
????case?DLL_THREAD_ATTACH:
????????//?當(dāng)進(jìn)程創(chuàng)建一個(gè)線程的時(shí)候,用于告訴DLL執(zhí)行與線程相關(guān)的初始化(非主線程執(zhí)行)
????????//?A?thread?is?bing?created.
????????break;
????case?DLL_THREAD_DETACH:
????????//?系統(tǒng)調(diào)用?ExitThread?線程退出前,即將終止的線程通過告訴DLL執(zhí)行與線程相關(guān)的清理
????????//?A?thread?is?exiting?cleanly.
????????break;
????case?DLL_PROCESS_DETACH:
????????//?將一個(gè)DLL從進(jìn)程的地址空間時(shí)調(diào)用
????????//?The?DLL?is?being?unmapped?from?the?process'?address?space.
????????break;
????}
????return?(TRUE);?//?Used?only?for?DLL_PROCESS_ATTACH
}

載入卸載庫

FreeLibraryAndExitThread 函數(shù)聲明

//?載入庫
HMODULE?WINAPI?LoadLibrary(
??_In_?LPCTSTR?lpFileName
)
;
HMODULE?LoadLibraryExA(
??LPCSTR?lpLibFileName,
??HANDLE?hFile,
??DWORD??dwFlags
)
;
//?若要在通用?Windows?平臺(tái)(UWP)應(yīng)用中加載?Win32?DLL,需要調(diào)用?LoadPackagedLibrary,而不是?LoadLibrary?或?LoadLibraryEx
HMODULE?LoadPackagedLibrary(
??LPCWSTR?lpwLibFileName,
??DWORD???Reserved
)
;

//?卸載庫
BOOL?WINAPI?FreeLibrary(
??_In_?HMODULE?hModule
)
;
//?卸載庫和退出線程
VOID?WINAPI?FreeLibraryAndExitThread(
??_In_?HMODULE?hModule,
??_In_?DWORD???dwExitCode
)
;

顯示地鏈接到導(dǎo)出符號(hào)

GetProcAddress 函數(shù)聲明

FARPROC?GetProcAddress(
??HMODULE?hInstDll,
??PCSTR?pszSymbolName??//?只能接受?ANSI?字符串,不能是?Unicode
)
;

DumpBin.exe 查看 DLL 信息

VS 的開發(fā)人員命令提示符 使用 DumpBin.exe 可查看 DLL 庫的導(dǎo)出段(導(dǎo)出的變量、函數(shù)、類名的符號(hào))、相對(duì)虛擬地址(RVA,relative virtual address)。如:

DUMPBIN?-exports?D:\mydll.dll
DLL 頭文件

//?MyLib.h

#ifdef?MYLIBAPI

//?MYLIBAPI?應(yīng)該在全部?DLL?源文件的?include?"Mylib.h"?之前被定義
//?全部函數(shù)/變量正在被導(dǎo)出

#else

//?這個(gè)頭文件被一個(gè)exe源代碼模塊包含,意味著全部函數(shù)/變量被導(dǎo)入
#define?MYLIBAPI?extern?"C"?__declspec(dllimport)

#endif

//?這里定義任何的數(shù)據(jù)結(jié)構(gòu)和符號(hào)

//?定義導(dǎo)出的變量(避免導(dǎo)出變量)
MYLIBAPI?int?g_nResult;

//?定義導(dǎo)出函數(shù)原型
MYLIBAPI?int?Add(int?nLeft,?int?nRight);
DLL 源文件

//?MyLibFile1.cpp

//?包含標(biāo)準(zhǔn)Windows和C運(yùn)行時(shí)頭文件
#include?

//?DLL源碼文件導(dǎo)出的函數(shù)和變量
#define?MYLIBAPI?extern?"C"?__declspec(dllexport)

//?包含導(dǎo)出的數(shù)據(jù)結(jié)構(gòu)、符號(hào)、函數(shù)、變量
#include?"MyLib.h"

//?將此DLL源代碼文件的代碼放在此處
int?g_nResult;

int?Add(int?nLeft,?int?nRight)
{
????g_nResult?=?nLeft? ?nRight;
????return?g_nResult;
}

DLL 庫的使用(運(yùn)行時(shí)動(dòng)態(tài)鏈接 DLL)

DLL 庫的使用(運(yùn)行時(shí)動(dòng)態(tài)鏈接 DLL)

//?A?simple?program?that?uses?LoadLibrary?and?
//?GetProcAddress?to?access?myPuts?from?Myputs.dll.?

#include??
#include??

typedef?int?(__cdecl?*MYPROC)(LPWSTR);?

int?main(?void?)?
{?
????HINSTANCE?hinstLib;?
????MYPROC?ProcAdd;?
????BOOL?fFreeResult,?fRunTimeLinkSuccess?=?FALSE;?

????//?Get?a?handle?to?the?DLL?module.

????hinstLib?=?LoadLibrary(TEXT("MyPuts.dll"));?

????//?If?the?handle?is?valid,?try?to?get?the?function?address.

????if?(hinstLib?!=?NULL)?
????{?
????????ProcAdd?=?(MYPROC)?GetProcAddress(hinstLib,?"myPuts");?

????????//?If?the?function?address?is?valid,?call?the?function.

????????if?(NULL?!=?ProcAdd)?
????????{
????????????fRunTimeLinkSuccess?=?TRUE;
????????????(ProcAdd)?(L"Message?sent?to?the?DLL?function\n");?
????????}
????????//?Free?the?DLL?module.

????????fFreeResult?=?FreeLibrary(hinstLib);?
????}?

????//?If?unable?to?call?the?DLL?function,?use?an?alternative.
????if?(!?fRunTimeLinkSuccess)?
????????printf("Message?printed?from?executable\n");?

????return?0;
}

運(yùn)行庫(Runtime Library)

典型程序運(yùn)行步驟

  1. 操作系統(tǒng)創(chuàng)建進(jìn)程,把控制權(quán)交給程序的入口(往往是運(yùn)行庫中的某個(gè)入口函數(shù))

  2. 入口函數(shù)對(duì)運(yùn)行庫和程序運(yùn)行環(huán)境進(jìn)行初始化(包括堆、I/O、線程、全局變量構(gòu)造等等)。

  3. 入口函數(shù)初始化后,調(diào)用 main 函數(shù),正式開始執(zhí)行程序主體部分。

  4. main 函數(shù)執(zhí)行完畢后,返回到入口函數(shù)進(jìn)行清理工作(包括全局變量析構(gòu)、堆銷毀、關(guān)閉I/O等),然后進(jìn)行系統(tǒng)調(diào)用結(jié)束進(jìn)程。

一個(gè)程序的 I/O 指代程序與外界的交互,包括文件、管程、網(wǎng)絡(luò)、命令行、信號(hào)等。更廣義地講,I/O 指代操作系統(tǒng)理解為 “文件” 的事物。

glibc 入口

_start -> __libc_start_main -> exit -> _exit

其中 main(argc, argv, __environ) 函數(shù)在 __libc_start_main 里執(zhí)行。

MSVC CRT 入口

int mainCRTStartup(void)

執(zhí)行如下操作:

  1. 初始化和 OS 版本有關(guān)的全局變量。

  2. 初始化堆。

  3. 初始化 I/O。

  4. 獲取命令行參數(shù)和環(huán)境變量。

  5. 初始化 C 庫的一些數(shù)據(jù)。

  6. 調(diào)用 main 并記錄返回值。

  7. 檢查錯(cuò)誤并將 main 的返回值返回。

C 語言運(yùn)行庫(CRT)

大致包含如下功能:

  • 啟動(dòng)與退出:包括入口函數(shù)及入口函數(shù)所依賴的其他函數(shù)等。

  • 標(biāo)準(zhǔn)函數(shù):有 C 語言標(biāo)準(zhǔn)規(guī)定的C語言標(biāo)準(zhǔn)庫所擁有的函數(shù)實(shí)現(xiàn)。

  • I/O:I/O 功能的封裝和實(shí)現(xiàn)。

  • 堆:堆的封裝和實(shí)現(xiàn)。

  • 語言實(shí)現(xiàn):語言中一些特殊功能的實(shí)現(xiàn)。

  • 調(diào)試:實(shí)現(xiàn)調(diào)試功能的代碼。

C語言標(biāo)準(zhǔn)庫(ANSI C)

包含:

  • 標(biāo)準(zhǔn)輸入輸出(stdio.h)

  • 文件操作(stdio.h)

  • 字符操作(ctype.h)

  • 字符串操作(string.h)

  • 數(shù)學(xué)函數(shù)(math.h)

  • 資源管理(stdlib.h)

  • 格式轉(zhuǎn)換(stdlib.h)

  • 時(shí)間/日期(time.h)

  • 斷言(assert.h)

  • 各種類型上的常數(shù)(limits.h
本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉
關(guān)閉