套接字通信就是網絡通信
在網絡通信時,客戶端和服務器的比例是N:1
服務器如何處理多個客戶端的請求
并發處理方式
1.多線程并發處理->線程池并發處理,線程池可以對多個線程進行管理
2.多進程->進程池
3.io多路轉接,使用select或者epoch進行處理,使用io轉接函數,可以在單線程的情況下處理多個客戶端的請求,如果io轉接搭配多線程使用就可以大大提高工作效率
4.使用開源框架:livenent開源的網絡通信框架,天然支持高并發
客戶端業務流程復雜
需要同時進行軟件的上傳和下載,在這種情況下就需要和服務器端建立多個連接,這樣才能提高效率,就可以在客戶端創建一個套接字連接池,每個連接對應一個要處理的業務流程,因為發起了多個連接,每個連接都需要處理,這時候就需要使用多線程,因此套接字連接池和多線程是 搭配使用的,同樣的,也可以套接字連接池和線程池搭配使用
由于c++里面沒有用于通信的套接字類,需要基于c語言的api封裝出對應的用于通信的c++類
1.概念
局域網和廣域網
局域網:局域網將一定區域內的各種計算機、外部設備和數據庫連接起來形成計算機通信的私有網絡。
廣域網:又稱廣域網、外網、公網。是連接不同地區局域網或城域網計算機通信的遠程公共網絡。
ip:網絡協議。ip地址用來表示計算機在網絡中的地址
端口:用端口來標識進程地址
ip+端口就可以知道是哪臺電腦的哪個進程
iso/osi模型
應用層
表示層 應用層
會話層
傳輸層 傳輸層 tcp,udp 傳輸層協議
網絡層 網絡互聯層 ip協議(ipv4,ipv6)
數據鏈路層 網絡接口層 以太網幀協議(底層協議不需要搞明白,只需要搞明白對應的套接字接口怎么去調用,以及套接字通信的流程)
物理層
物理層:負責最后將信息編碼成電流脈沖或其它信號用于網上傳輸
數據鏈路層:
數據鏈路層通過物理網絡鏈路供數據傳輸。
規定了0和1的分包形式,確定了網絡數據包的形式;
網絡層
網絡層負責在源和終點之間建立連接;
此處需要確定計算機的位置,通過IPv4,IPv6格式的IP地址來找到對應的主機
傳輸層
傳輸層向高層提供可靠的端到端的網絡數據流服務。
每一個應用程序都會在網卡注冊一個端口號,該層就是端口與端口的通信
會話層
會話層建立、管理和終止表示層與實體之間的通信會話;
建立一個連接(自動的手機信息、自動的網絡尋址);
表示層:
對應用層數據編碼和轉化, 確保以一個系統應用層發送的信息 可以被另一個系統應用層識別;
網絡協議:全世界都認可的在網路通信過程中使用的一種數據的固定通信格式
數據是怎么在計算機之間進行傳遞的
我們要發送的數據都是應用層的數據,應用層的數據可以使用應用層的協議(比如ftp,http)進行包裝,應用層包裝好之后繼續向下傳遞就到了傳輸層,傳輸層還需要繼續進行打包,打包之后還需要再次向下傳遞就到了網絡層,網絡層繼續向下傳遞就到了網絡接口層,數據再次打包得到一個報文,這個報文通過網口發送給對方,對方計算機接收到這個數據之后,先對網絡接口層的這個數據進行解包操作,解出來后就得到了網絡層的一個數據包,網絡層繼續向上傳遞就到了傳輸層,數據在傳輸層解剖繼續向上傳遞到達應用層,就需要由程序員去處理,先看看我們的數據有沒有被應用層的協議進行封裝,如果封裝了,程序員自己把他解開,比如基于http進行解包才能拿到原始數據。但如果沒有使用相關協議對應用層數據進行打包,那么我們從傳輸層拿到數據就是原始數據了,直接處理就可以了
應用層以下,程序員默認情況下不需要做任何處理的,這些都是由內核來完成的,我們只需要把應用層這個數據搞清楚就行了
應用層數據就兩種情況:1.不進行數據的打包
2.打包的數據 如果說對應用層的數據進行了封裝,接收到這個數據之后需要在應用層把這個數據按照發送端的協議格式再解開就能得到原始數據
在網絡通信的時候, 程序猿需要負責的應用層數據的處理(最上層)
應用層的數據可以使用某些協議進行封裝, 也可以不封裝
程序猿需要調用發送數據的接口函數,將數據發送出去
程序猿調用的API做底層數據處理
傳輸層使用傳輸層協議打包數據
網絡層使用網絡層協議打包數據
網絡接口層使用網絡接口層協議打包數據
數據被發送到internet
接收端接收到發送端的數據
程序猿調用接收數據的函數接收數據
調用的API做相關的底層處理:
網絡接口層拆包 ==> 網絡層的包
網絡層拆包 ==> 網絡層的包
傳輸層拆包 ==> 傳輸層數據
如果應用層也 使用了協議對數據進行了封裝,數據的包的解析需要程序猿做
套接字通信就是網絡通信就是socket通信
socket:研發的一套接口
問題:在發送端把數據封裝好后,肯定要把它先存到一塊內存中,然后再通過網絡進行發送,接收端收到這個數據后,也是要先把數據存到一塊內存中,然后再進行解析
如果發送端A和接收端B在內存中存儲數據的順序不一致(比如發送端從低地址位到高地址位存儲123456,而接收端可能是654321這樣),就會導致在接收端解析不出來發送端相同的數據
所以必須要求兩段在內存中處理數據的順序是一致的,即要制定一個規則,即指定數據在發送過程中的字節序(即數據在內存中的存儲順序)
字節序,顧名思義字節的順序,就是大于一個字節類型的數據在內存中的存放順序,也就是說對于單字符來說是沒有字節序問題的,字符串是單字符的集合,因此字符串也沒有字節序問題。
對于int long這些非單字節結構的數據類型,它們都需要由多個字節才能夠組成一個完整的整體
數據在內存中的存儲順序主要有兩種,分別是大端(網絡字節序)和小端(主機字節序),通常所用的pc機在內存中的存儲順序,就是按照小端的順序存儲的,在進行網絡通信的時候,數據是按照大端來存儲的,比如在套接字通信的時候發送的數據需要把數據從小端轉換成大端進行發送,接收到數據之后,還需要把大端轉換成小端在本地主機上進行存儲
小端(主機字節序):數據的低位字節存儲到低地址位,高位字節存儲到高地址位(低低高高)
大端(網絡字節序):相反(低高高低)
大小端相互轉換的操作函數
#include <arpa/inet.h>
// u:unsigned
// 16: 16位, 32:32位
// h: host, 主機字節序
// n: net, 網絡字節序
// s: short
// l: int
//這組函數主要是對16位和32位的整形數進行轉換
// 這套api主要用于 網絡通信過程中 IP 和 端口 的 轉換
// 將一個短整形從主機字節序 -> 網絡字節序
uint16_t htons(uint16_t hostshort);
// 將一個整形從主機字節序 -> 網絡字節序
uint32_t htonl(uint32_t hostlong); // 將一個短整形從網絡字節序 -> 主機字節序
uint16_t ntohs(uint16