網絡編程遇到相關問題

爲何出現粘包問題?

TCP協議就相似於打電話
只有在TCP協議中才會出現粘包現象,由於TCP協議是流式協議
它的特色是將數據量小而且時間間隔比較短的數據一次性打包發送出去
本質其實仍是由於咱們不知道須要接收的數據的長短

如何解決粘包問題?

1 發送數據直接先告訴對方數據量的大小
2 利用struct模塊定製咱們本身的消息傳輸協議

TCP的大文件上傳

客戶端:
        1.製做字典的報頭(固定4個長度)
        2.發送報頭
        3.發送字典
        4.最後再發真實數據
服務端:
        1.先接收4個長度的報頭
        2.解析報頭獲取字典的長度
        3.接收字典數據  從字典中獲取真實數據的詳細信息
        4.接收真實數據

udp協議

UDP協議就相似於發短信
1.udp協議客戶端容許發空
2.udp協議不會粘包
3.udp協議服務端不存在的狀況下,客戶端照樣不會報錯
4.udp協議支持併發

UDP叫數據報協議,意味着發消息都帶有數據報頭
udp的server不須要就行監聽也不須要創建鏈接
在啓動服務以後只能被動的等待客戶端發送消息過來,客戶端發送消息的時候,要帶上服務端的地址
服務端在回覆消息的時候,也須要帶上客戶端的地址

多道技術

解決cpu在執行程序,遇到io時,不幹活的狀況
時間上的複用(單個cpu的電腦上,起多個應用程序。cpu快速切換,給人的感受是同時運行)
空間上的複用(多個程序共一套硬件設備,它是多道技術實現時間上的複用的基礎,否則還要去硬盤讀數據)
一個任務佔用cpu時間過長或被操做系統強行剝奪走cpu的執行權限(比起串行效率反而下降)
一個任務執行過程當中遇到io操做,也會被操做系統強行剝奪走cpu的執行權限(比起串行效率提升)

串行|併發

串行:一個程序完完整整的運行完畢,才能運行下一個程序
併發:看上去像同時運行

進程理論

程序:一堆代碼
進程:正在運行的程序
進程是一個實體,每個進程都有它本身獨立的內存空間

同步和異步:針對任務的提交方式

同步:提交任務以後原地等待任務的返回結果,期間不作任何事!
異步:提交任務以後,不等待任務的返回結果,執行運行下一行代碼!

阻塞與非阻塞:針對程序運行的狀態

阻塞:遇到io操做   >>> 阻塞態
非阻塞:就緒或者運行態  >>> 就緒態,運行態

互斥鎖:鎖千萬不要隨意去用

會將併發變成串行,犧牲了效率可是保證了數據的安全
鎖必定要在主進程中建立,給子進程去用
解決多個進程操做同一份數據,形成數據不安全的狀況
加鎖會將併發變成串行
鎖一般用在對數據操做的部分,並非對進程全程加鎖
一把鎖不能同時被多我的使用,沒有搶到的人,就一直等待鎖釋放

生產者消費者模型

生產者:生產數據(作包子的)
消費者:處理數據(吃包子的)
二者之間的通訊介質:隊列/管道
供需不平衡:
    隊列: 
        生產者生產的數據放到隊列裏面
        消費者去隊列裏面獲取數據

IPC機制

進程間通訊
    進程與進程之間是數據隔離的
    管道/隊列(管道+鎖)
    隊列:先進先出
    堆棧:先進後出
    q.put()  放入值
    q.get()  獲取隊列裏面的值(同一時刻只能有一個任務來隊列中獲取數據)
    二者在存放值和取值的時候都會出現阻塞的狀況(隊列滿了,隊列空了)

線程理論

把操做系統比喻成工廠
進程:資源單位(工廠裏面的車間)
線程:執行單位(車間裏面的流水線)
任何一個進程都自帶一個"主"線程
進程中的線程數據是共享的,
開起進程的開銷要遠遠大於開啓線程的開銷
開啓進程:申請空間,拷貝代碼都須要耗時
開啓線程:開銷極小,幾乎在代碼執行的同時線程就已經建立

線程之間數據共享

線程之間數據共享
多個線程操做同一份數據???出現數據不安全的狀況
涉及到多個線程或進程操做同一份數據的時候,一般都須要將並行併發變成串行
雖然犧牲了效率可是提升了數據的安全性
針對不一樣的數據,須要加不一樣的鎖
鎖(獨立衛生間)

GIL全局解釋器鎖

只在Cpython解釋器中
因爲Cpython內存管理不是線程安全的!
同一進程下的多個線程在同一時刻只能有一個線程被執行
必須先搶解釋器才能被cpu執行
GIL是加在Cpython解釋器上的一把鎖,並不能保證數據的安全,想保證數據的安全,就必須加不一樣的鎖

python內存管理

內存管理>>>垃圾回收機制
1.引用計數
2.標記清除
3.分代回收

死鎖與遞歸鎖

即使你記住了每acquire一次就release一次的操做,也會產生死鎖現象
遞歸鎖:能夠連續的acquire(),每acquire()一次計數加一

信號量

若是把互斥鎖比喻成獨立衛生間,那麼信號量就至關於多個衛生間,一個能夠指定多個線程訪問

event事件

event = Event()
        
event.set()  # 告訴另一個子線程 你能夠運行了
        
event.wait()  # 等待別人給我發set()信號

socket服務端實現併發

固定的ip和port
24小時提供服務
可以實現併發

進程池線程池

線程不可能無限制的開下去,總要消耗和佔用資源

進程池線程池概念:硬件有極限,爲了減輕硬件壓力,因此有了池的概念
池:
    爲了減緩計算機硬件的壓力,避免計算機硬件設備崩潰
    雖然減輕了計算機硬件的壓力,可是必定程度上下降了持續的效率
進程池線程池:
    爲了限制開設的進程數和線程數,從而保證計算機硬件的安全

- concurrent.futures模塊導入
- 線程池建立(線程數=cpu核數*5左右)
- submit提交任務(提交任務的兩種方式)
- 異步提交的submit返回值對象
- shutdown關閉池並等待全部任務運行結束
- 對象獲取任務返回值
- 進程池的使用,驗證進程池在建立的時候裏面固定有指定的進程數
- 異步提交回調函數的使用

協程,io密集型會提升效率

- 進程:資源單位
- 線程:執行單位
- 協程:單線程下實現併發(可以在多個任務之間切換和保存狀態來節省IO),這裏注意區分操做系統的切換+保存狀態是針對多個線程而言,而咱們如今是想在單個線程下本身手動實現操做系統的切換+保存狀態的功能

協程這個概念徹底是程序員本身想出來的東西,它對於操做系統來講根本不存在。操做系統只知道進程和線程。
注意:
    並非單個線程下實現切換+保存狀態就能提高效率,由於你多是沒有遇到io也切,那反而會下降效率

實現高併發的原理

將單個線程的效率提高到最高,多進程下開多線程,多線程下用協程>>> 實現高併發!!!

協程實現服務端客戶端通訊

連接和通訊都是io密集型操做,咱們只須要在這二者之間來回切換其實就能實現併發的效果
服務端監測連接和通訊任務,客戶端起多線程同時連接服務端
相關文章
相關標籤/搜索