天天看點

網絡程式設計,從socket到epoll

網絡程式設計,從socket到epoll

參考連結:https://www.bilibili.com/video/BV11Z4y157RY?p=2&spm_id_from=pageDriver

socket基本知識:

socket分類:

socekt提供了流和資料報兩種通信機制,即流socket和資料報socket。

簡單的socket通信流程:

網絡程式設計,從socket到epoll

先建立通道——>再收/發封包(使用recv函數和send函數進行收/發封包)。

一個伺服器有兩個網端(網卡),但是左邊的兩個ip位址隻能通過192.168.10.10進行通信。

網絡程式設計,從socket到epoll

相關的庫函數:

recv()函數:是等待。

close(socket)關閉資源。

AF_UNIX()函數。

ip位址的範圍:0.0.0.0~255.255.255.255。

ipv4和ipv6的差別,目前更常用的是ipv4。

socket的參數:socket(AFINET,SOCK_STREAM,0)。

面試問題:

在一個程式裡面最多打開多少個檔案數?答案:1024個。可以搜尋“linux一般打開檔案的數量”。

結構體(重要):

socket結構體:

網絡程式設計,從socket到epoll

 hostent結構體:

網絡程式設計,從socket到epoll

 兩個函數:

字元串ip位址和網絡位元組序ip位址互相轉換。網絡位元組序ip位址是整數int類型。

網絡程式設計,從socket到epoll

網絡位元組順序:

網絡位元組序轉化為主機位元組序時,一定要注意是否需要轉換。網絡位元組序是确定的。

網絡位元組順序是TCP/IP中規定好的一種資料表示格式,它與具體的CPU類型、作業系統等無關,進而可以保證資料在不同主機之間傳輸時能夠被正确解釋。網絡位元組順序采用big-endian(大端)排序方式。

參考連結:https://baike.baidu.com/item/%E7%BD%91%E7%BB%9C%E5%AD%97%E8%8A%82%E5%BA%8F/12610557

主機位元組序

主機位元組序,即CPU存儲資料時采用的位元組順序。不同的CPU設計時采用的位元組序是不同的。平常大多數PC與伺服器如果使用的是Intel與AMD CPU,一般都是little endian。

參考連結:https://blog.csdn.net/K346K346/article/details/79053136

設定伺服器socket的SO_REUSEADDR屬性

網絡程式設計,從socket到epoll

listen()、connect()和accept()函數

網絡程式設計,從socket到epoll

 listen的socket隊列:

網絡程式設計,從socket到epoll

TCP的三次握手:

網絡程式設計,從socket到epoll

send()函數:

傳回已發送的字元數。

RECV函數:

用于接受對端通過socket發送過來的資料。應用程式都用recv函數接收來自tcp連接配接的另一端發送過來的資料。

TCP封包分包和粘包

網絡程式設計,從socket到epoll

多程序網絡服務端架構freecplus架構

參考連結:https://www.freecplus.net/9ebb8276265b404488a3415be224ed85.html

Writen和Readn

兩個函數readn和writen的功能是讀、寫指定的N位元組資料,并處理傳回值小于要求值的情況。這兩個函數隻是按需多次調用read和write直至讀、寫了N位元組資料。

參考連結:https://www.cnblogs.com/nufangrensheng/p/3559381.html

I/O複用,之後講

孤兒程序和僵屍程序

定義:

孤兒程序:一個父程序退出,而它的一個或多個子程序還在運作,那麼那些子程序将成為孤兒程序。孤兒程序将被init程序(程序号為1)所收養,并由init程序對它們完成狀态收集工作。

僵屍程序:一個程序使用fork建立子程序,如果子程序退出,而父程序并沒有調用wait或waitpid擷取子程序的狀态資訊,那麼子程序的程序描述符仍然儲存在系統中。這種程序稱之為僵屍程序。

僵屍程序解決辦法:

(1)通過信号機制

子程序退出時向父程序發送SIGCHILD信号,父程序處理SIGCHILD信号。在信号處理函數中調用wait進行處理僵屍程序。

(2)兩次fork

将子程序成為孤兒程序,進而其的父程序變為init程序,通過init程序(程序号是1)可以處理僵屍程序。

參考連結:https://www.cnblogs.com/anker/p/3271773.html

C語言程式運作日志

關注點有:

程式執行的過程

處理資料的情況

記錄異常和錯誤

程式的調試

日志檔案的基本操作:

類的聲明

打開日志檔案

寫入日志檔案 

write寫入時間,writeex不寫入時間。

關閉日志檔案

目錄操作:

檔案操作:

多程序和多線程服務程式的日志:

使用同一個日志,可能會産生競争。

多程序式的日志檔案不能切換。

如果使用同一個日志檔案,用鎖太麻煩,還會影響程式的效果,一般分開寫日志。

程序間通信:

程序間通信包括:

1)資料傳輸

2)共享資料

3)通知事件

4)程序控制

程序間通信方式包括6種:

1)管道:有無名管道和命名管道。

2)消息隊列(message)

3)信号(signal)

4)共享記憶體(shared memory):多個程序可以通路同一個程序空間。

5)信号量(semaphore):也叫信号燈,用于程序之間對共享資源進行加鎖。

6)套接字(socket)

在企業IT系統内部,消息隊列已經逐漸成為通信的核心手段,它具有低耦合、可靠投遞、廣播、流量控制、一緻性等一系列功能。當今有很多主流的消息中間件:Redis、Kafka、RabbitMQ、ZeroMQ,阿裡巴巴自主研發RocketMQ等。

管道和消息隊列不能用于多台伺服器之間。

參考連結:https://www.bilibili.com/video/BV1YD4y127aM?from=search&seid=9253392497960943444&spm_id_from=333.337.0.0

共享記憶體:

參考連結:https://www.bilibili.com/video/BV1YD4y127aM?p=2&spm_id_from=pageDriver

共享記憶體的操作:

網絡程式設計,從socket到epoll

 相關函數:

shmget函數:建立共享記憶體。先建立共享記憶體,建立不成功才再嘗試擷取(和semget函數相反)。
shmat函數:連接配接
shmdt函數:共享記憶體從目前程序中分離
shmctl函數:删除共享記憶體

其他的操作指令:

ipcs -m 可以檢視系統的共享記憶體。

ipcrm -m共享記憶體編号,可以删除共享記憶體編号。

nattch:

網絡程式設計,從socket到epoll

二進制信号量:

參考連結:https://www.bilibili.com/video/BV1YD4y127aM?p=3&spm_id_from=pageDriver

信号量隻允許程序進行等待信号和發送信号。

二進制信号量是最簡單的信号量。

ipcs -s:檢視信号燈。

網絡程式設計,從socket到epoll

ipcrm sem 425985:删除信号量425985

網絡程式設計,從socket到epoll

oracle信号量删除不了的。

相關函數:

semget:建立信号量。先擷取,如果不存在,再去建立。

擷取信号燈,如果信号燈不存在,建立它。信号燈建立成功後,還需要初始化為可用的狀态

semctl:删除信号燈。

semop:是一個結構體,等待( wait() )信号量。 op減一

semop:是一個結構體,釋放( post() )信号量。op加一

利用信号量給共享記憶體加鎖:

主要就是把信号量和共享記憶體的代碼結合在一起即可。

通用信号量和信号量集:

給多程序的socket伺服器增加業務邏輯:

網絡程式設計,從socket到epoll

補充:C++知識

C++重載:參數清單不同。函數重載僅僅是文法層面的,本質上它們是不同的函數,占用不同的記憶體,入口位址也不一樣。

C++引用:就是變量的别名,對引用的操作和對變量直接操作完全一樣。

參考連結https://www.bilibili.com/video/BV1tp4y1i7rL?p=82

C++運算符重載:如果類重載了==運算符,那麼就可以用==判斷兩個類是否相等。運算符重載的實作是通過operator關鍵字實作的。

參考連結:https://www.bilibili.com/video/BV1tp4y1i7rL?p=84

C++動态記憶體管理:有new和delete

參考連結:https://www.bilibili.com/video/BV1tp4y1i7rL?p=88

C++類的繼承和派生:當建立一個類時,如果待建立的類與另一個類存在某些共同特征,程式員不需要全部重新編寫成員變量和成員函數,隻需要指定繼承另一個類即可,被繼承的類稱為基類或者父類,建立的類稱為派生類和子類。

定義派生類的文法:

網絡程式設計,從socket到epoll

 子類沒有的函數,就會調用父類的函數。如果子類和父類都有相同的函數,是調用了子類還是父類的函數呢?

答:是調用子類的。

基類的指針可以指向基類對象,也可以指向派生類對象,但是不能通過基類的指針通路派生類的成員。

派生類的指針可以指向派生類對象,但是不能指向基類對象。

C++多繼承:C++類可以從多個基類繼承成員,文法如下:

網絡程式設計,從socket到epoll

 參考連結:https://www.bilibili.com/video/BV1tp4y1i7rL?p=89

C++類的多态:多态按照字面意思就是多種形态。當類之間存在繼承關系時,就可能會用到多态,調用成員函數時,會根據對象的類型來執行不同的函數。

靜态多态:函數重載就是一個簡單的靜态多态。

虛函數:是在基類中使用關鍵字virtual聲明的函數,在派生類中重新定義虛函數。

在程式中可以根據所調用的對象類型來選擇調用的函數,這種操作被稱為動态綁定,或後期綁定。

純虛函數:在基類中隻是申明虛函數,沒有函數的定義,在派生類中去實作函數的定義,這個時候就會用到純虛函數。

網絡程式設計,從socket到epoll

 C++接口(抽象類):接口描述了類的行為和功能,不需要累的功能實作。C++接口是用抽象類實作的。如果類中至少有一個函數被聲明為純虛函數,則這個類就是抽象類。

可用于執行個體化對象的類被稱為具體類。

參考連結:https://www.bilibili.com/video/BV1tp4y1i7rL?p=90

 抽象類不能直接通過new去執行個體化一個對象,那它就是不能執行個體化,要擷取抽象類的對象, 需要先用一個類繼承抽象類, 然後去執行個體化子類。

參考連結:https://cloud.tencent.com/developer/article/1448100

對socket通信的函數進行封裝:主程式代碼太多,可以分離出去,采用的方法就是封裝。

用戶端連伺服器的函數,可以封裝服務端ip和通信端口。

函數的聲明:

網絡程式設計,從socket到epoll

 函數的實作:

網絡程式設計,從socket到epoll

 構造函數和析構函數:

 構造函數是一個特殊的公共成員函數,它在建立類對象時會自動被調用,用于構造類對象。構造函數不允許有傳回類型。

析構函數是具有與類相同名稱的公共成員函數,前面帶有波浪符号(〜)。

參考連結:http://c.biancheng.net/view/1401.html

C++封裝的意義:

1)把資料初始化的代碼放在構造函數裡中;

2)把關閉socket等釋放資源的diamante放在析構函數中;

3)把socket定義為類的成員變量,類外部的代碼根本看不到socket。

4)代碼更簡潔,更安全。(析構函數自動調用并關閉socket,釋放資源)

Linux的多程序:

程序的概念:是針對系統不是針對程式員。對于程式員來說,面對的概念是程式,當輸入指令執行一個程式的時候,對系統而言,它将啟動一個程序。

程序就是正在記憶體中運作中的程式,linux下一個程序在記憶體裡有三個部分的資料,就是“代碼段”、“堆棧段”和“資料段”。

“堆棧段”存放的是程式的傳回位址、程式的參數以及程式的局部變量;“資料段”存放程式的全局變量、常數以及動态資料配置設定的資料空間(比如用new函數配置設定的空間)。

系統如果運作相同的程式,“堆棧段”和“資料段”是相同的嗎?

答:不同(相同的程式,處理的資料是不同的)。

程序的指令:

指令 ps 檢視程序

ps -ef 檢視系統全部的程序

ps -ef|more 檢視系統全部的程序,結果分頁顯示

網絡程式設計,從socket到epoll

ps -ef|grep :grep是搜尋我們需要的程序。

getpid()擷取本程式運作時程序的編号。

注意的細節:程序的編号是系統動态配置設定的,相同的程式在不同的時間執行,程序的編号是不同的。程序的編号會循環使用,但是,在同一時間,程序的編号是唯一的,也就是說,不管是任何時間,系統不可能存在兩個編号相同的程序。

多程序:

fork():fork()産生一個新的程序,函數傳回值pid是一個整數,在父程序中,傳回值是父程序的編号,在子程序中,傳回值是0。

網絡程式設計,從socket到epoll

 參考連結:https://www.bilibili.com/video/BV1tp4y1i7rL?p=99

多線程:

pthread_create:建立線程

pthread_exit:線程終止。還有另外兩種終止方法。

參考連結:https://www.bilibili.com/video/BV1tp4y1i7rL?p=109

檢視線程:

top -H

ps -xH|grep book261

線程同步:

參考連結:https://www.bilibili.com/video/BV1tp4y1i7rL?p=111

日常生活中,鎖有兩種,一種是不允許通路,另一種是資源忙,同一時間隻允許一個使用者占用,其他使用者必須等待。

線程的鎖的種類有:互斥鎖、讀寫鎖、條件變量、自旋鎖

信号燈。

互斥鎖:互斥機制是同一時刻隻允許一個線程占有共享的資源。

互斥鎖的過程:初始化、阻塞加鎖、非阻塞加鎖、解鎖。

C/C++程式中調試可執行程式:

參考連結:https://www.bilibili.com/video/BV1tp4y1i7rL?p=112

exec函數族:

exec函數族提供了一個在程序中啟動另一個程式執行的方法。它可以根據指定的檔案名或目錄名找到可執行檔案,并用它來取代原調用程序的資料段、代碼段和堆棧段,在執行完之後,原調用程序的内容除了程序号外,其他全部被新的程序替換了。另外,這裡的可執行檔案既可以是二進制檔案,也可以是Linux下任何可執行的腳本檔案。

參考連結:https://baike.baidu.com/item/exec%E5%87%BD%E6%95%B0%E6%97%8F/3489348?fromtitle=EXEC&fromid=9077756

網絡程式設計,從socket到epoll

 system函數:

提供了簡單的執行程式的方法,把需要執行的指令用一個參數傳給system函數。

Linux的靜态庫和動态庫

參考連結:https://www.bilibili.com/video/BV1tp4y1i7rL?p=113

網絡程式設計,從socket到epoll

 庫檔案和其它的源檔案一起編譯,是靜态編譯;庫檔案被作業系統載入記憶體執行是動态編譯。

.a是靜态庫,.so是動态庫。

靜态庫的優缺點:

網絡程式設計,從socket到epoll

 動态庫的優缺點:

網絡程式設計,從socket到epoll

https://cloud.tencent.com/developer/article/1448100

XML實戰應用之精髓

生成和解析xml字元串

xml應用的三個方面:

1)解析xml資料檔案

2)xml用于網絡通信

3)xml用于程式的參數

程式運作,參數非常多,一個個寫非常複雜,并且很容易出錯。是以應用xml,把參數通過xml傳遞,然後再解析xml即可。

4)把簡單的xml發揮到極緻:資料交換、資料同步。提高工作的效率。

參考連結:https://www.bilibili.com/video/BV15v411q7Yb?p=6

增加業務邏輯:

GetXMLBuffer()函數

TCP短連接配接與長連接配接

網絡程式設計,從socket到epoll

長連接配接的心跳機制:

網絡程式設計,從socket到epoll

心跳機制:就是每隔幾分鐘發送一個固定資訊給服務端,服務端收到後回複一個固定資訊如果服務端幾分鐘内沒有收到用戶端資訊則視用戶端斷開。

參考連結:https://blog.csdn.net/aspnet_lyc/article/details/37318861

心跳封包:<bizcode>0</biz000>

搭建多線程網絡伺服器架構:

參考連結:https://www.bilibili.com/video/BV11Z4y157RY?p=29

https://www.bilibili.com/video/BV1zf4y1Q7Nj?p=12

性能測試的重要性:

網絡程式設計,從socket到epoll

測試服務端并發性能:

網絡程式設計,從socket到epoll

測試服務端業務性能:

網絡程式設計,從socket到epoll

多程序和多線程服務端性能差異:

mpserver:多線程

mtserver:多程序

在測試業務性能方面:多線程占用CPU和記憶體上面,更有優勢。

網絡程式設計,從socket到epoll

參考連結:https://blog.csdn.net/lishenglong666/article/details/8557215

 多程序和多線程如何選擇?

 1)需要頻繁建立銷毀的優先用線程

2)需要進行大量計算的優先使用線程

3)強相關的處理用線程,弱相關的處理用程序

4)可能要擴充到多機分布的用程序,多核分布的用線程

測試用戶端的響應時間:

網絡程式設計,從socket到epoll

測試網絡帶寬:

網絡程式設計,從socket到epoll

I/O複用介紹

網絡程式設計,從socket到epoll

 select、poll、spoll

網絡程式設計,從socket到epoll

 參考連結:https://www.cnblogs.com/yungyu16/p/13066744.html

Select:

Select的流程:

網絡程式設計,從socket到epoll

 Select的逾時機制:

應用fd_set實作seclect的超乎機制。

網絡程式設計,從socket到epoll

 select模型會丢失事件和資料嗎?

答:不會。select采用水準觸發的方式,如果報告fd後事件沒有被處理或者資料沒有被完全讀取,那麼下次select時會再次報告該id,也就是說select不會丢失事件和資料。

參考連結:https://www.136.la/jingpin/show-204521.html

select缺點是:

網絡程式設計,從socket到epoll
網絡程式設計,從socket到epoll

 pselect函數可以了解一下。

select優勢是:

實作跨平台,時間精度高(ns級别)

select的基本流程:

網絡程式設計,從socket到epoll

位圖Bitmap的原理:

網絡程式設計,從socket到epoll
網絡程式設計,從socket到epoll

poll模型的原理和實作:

poll概念:

poll本質上和select沒有差別,它将使用者傳入的數組拷貝到核心空間,然後查詢每個fd對應的裝置狀态,如果裝置就緒則在裝置等待隊列中加入一項并繼續周遊,如果周遊完所有fd後沒有發現就緒裝置,則挂起目前程序,直到裝置就緒或者主動逾時,被喚醒後它又要再次周遊fd。這個過程經曆了多次無謂的周遊。

參考連結:https://www.cnblogs.com/yungyu16/p/13066744.html

網絡程式設計,從socket到epoll

參考連結:https://www.bilibili.com/video/BV11Z4y157RY?p=44

 poll函數和參數:

網絡程式設計,從socket到epoll

epoll模型的原理和實作:

epoll模型的函數和參數:

epoll_create

epoll_ctl

epoll_wait

網絡程式設計,從socket到epoll

 參考連結:https://www.bilibili.com/video/BV11Z4y157RY?p=45&spm_id_from=pageDriver

網絡程式設計,從socket到epoll
網絡程式設計,從socket到epoll
網絡程式設計,從socket到epoll

epoll的水準觸發和邊緣觸發:

網絡程式設計,從socket到epoll

 事件沒有全部被處理或者資料沒有被全部讀取,epoll會在下次報告給fd,那麼就是邊緣觸發。如果立即報告給fd,就是水準觸發。

epoll應用場景:

  • 對于連接配接特别多,活躍的連接配接特别少
  • 典型的應用場景為一個需要處理上萬的連接配接伺服器,例如各種app的入口伺服器,例如qq

IO五種模型:

1)阻塞IO

最傳統的一種IO模型,即在讀寫資料過程中會發生阻塞現象。當使用者線程發出IO請求之後,核心會去檢視資料是否就緒,如果沒有就緒就會等待資料就緒,而使用者線程就會處于阻塞狀态,使用者線程交出CPU。當資料就緒之後,核心會将資料拷貝到使用者線程,并傳回結果給使用者線程,使用者線程才解除block狀态。

2)非阻塞IO

3)IO多路複用

4)信号驅動IO

5)異步IO

I/O複用中的寫事件:

I/O複用的其它知識:

網絡程式設計,從socket到epoll

 參考連結:https://www.bilibili.com/video/BV11Z4y157RY?p=48&spm_id_from=pageDriver

雪兒言