網絡編程+並發編程—總結

網絡編程+併發編程

架構:B/S 和 C/S

B/S:充分發揮PC機的性能

C/S:統一了應用的接口,隸屬於CS架構

OSI模型 七層

我們用五層

應用層http協議 https協議 ftp協議

傳輸層tcp udp 協議(四層交換機)

網絡層IP協議路由器(?)(三次交換機)

數據鏈路層arp協議,交換機 (二層交換機)

物理層網卡,雙絞線 (傳輸電信號)

Arp協議:通過目標ip地址獲取目標mac地址

物理地址:mac地址全球唯一,每個電腦的網卡上

Ip地址:四位點分十進制三十二位點分二進制

交換機的通信方式:

單播:點對點

組播:點對多

廣播:向多個pc端發送數據包

交換機和路由器的區別?

交換機是組織局域網的,經過內部處理解析數據,將數據已點對點,點對多的方式發送給目標

路由器是跨網段的數據傳輸,路由出網絡傳輸的最佳路徑

socket 介於應用層和傳輸層的socket抽象層

Tcp:面向連接的,雙全工的 面向字節流的,安全可靠,會發生黏包,只可以一個客戶端訪問。 三次握手,四次揮手

Udp:無連接的,面向數據報的,不安全,不可靠。可以同時和多個客戶端通信

三次握手:(必須是客戶點先發起)

1.客戶端發起請求鏈接服務端

2.服務端收到請求,向客戶端發送可以連接的請求

3.客服端收到連接,連接成功

四次揮手:(客戶端和服務端都可以發起)

1.客戶端發起斷開連接的請求

2.服務端收到請求,然後準備斷開連接的一些事物

3.服務端發送請求,我已經準備完畢,可以斷開了

4.客戶端收到請求,斷開連接。

為什麼會發生黏包:因為有緩存機制,連續發或者連續收。(在數據傳輸過程中,接收數據端接收數據時不知道該如何接收,造成的數據混亂現象)

合包機制:nagle算法 — 發數據的時候一點一點發,但是接收的時候會一次收到。

拆包機制:發送的數據太大,分開發送,接收的時候,最後不能剛剛接完,就會發生黏包。

都是發生在發送端。

如何解決黏包?

自定義表頭:用struct模塊,事先將要發送文件的大小存下來,發送 過去,然後按著指定數據開始接收。

Struct 模塊 可以將一個整數,封裝為一個指定(一般為4)字節數的數字,這樣接收端就可以指定大小接收這個數字。

操作系統

Dos系統#單用戶單任務

Windows系統#單用戶多任務(早起的Windows)

Unix系統#多用戶多任務

操作系統的作用:1)封裝接口,讓用戶方便使用 2)對系統資源的分配與調度

計算機的五大組成部分:運算器。控制器。存儲器。輸入設備。輸出設備。

編程語言發展史:機器語言,彙編語言,高級語言

並行:(兩件事或者多件事)同一時間點,同時執行 (多個CPU)

併發:(兩件事或者多件事)同一時間間隔,交替執行

阻塞:程序因為類似IO等待、等待時間等導致無法繼續執行

非阻塞:程序遇到類似於IO操作時,不再阻塞等待,如果沒有及時的處理IO,就會報錯或者跳過等待其他操作,

同步:某一個任務的執行必須依賴另一個任務的返回結果

異步:一個任務的執行,不需要依賴另一個任務的返回,只需要告訴另一個任務一聲

進程:cpu資源分配的最小單位 進程由三部分組成:代碼段,數據段,PCB(進程控制塊)

線程:cpu資源調度的最小單位線程由三部分組成:代碼段,數據段,TCB(線程控制塊)

進程的三大基本狀態:

就緒狀態:已經獲得運行所需的所有資源,除CPU

執行狀態:已經獲得所有資源包括CPU,處於正在運行

阻塞狀態:因為各種原因,進程放棄了CPU,導致進程無法繼續執行,此時進程處於內存中,繼續等待獲取CPU的一種狀態。ß

進程學的東西: multiprocessing

1)Process模塊

線程的創建

1)直接創建

p = Process(target = func, argest = (元組形式, 為func所傳的參數)) #實例化進程對象

2)繼承 (Process)

多線程的開啟1)for循環2)多個對象實例化

方法:

start()#開啟進程

join()#感知進程的結束,異步變同步

is_alive()#判斷進程是否存活

terminate()#殺死一個進程

屬性:

name#獲取進程名

pid#獲取進程號

daemon = True #守護進程

守護進程的特點:

#當主進程代碼結束後,守護進程隨主進程結束

#守護進程不能再創建子進程

#守護進程必須在start之前

2)鎖 Lock模塊(互斥鎖/同步鎖)

lock = Lock()#實例化一個鎖對象

lock.acquire()#上鎖

lock.release()#解鎖

RLock模塊(遞歸鎖)

遞歸鎖可以同時acquire多次,但是必須acquire幾次就必須release幾次。都在就會陷入死鎖狀態

死鎖

典型的例子:科學家吃麵 (一個人拿著面,一個人拿著叉子,到最後誰也吃不上面)

信號量Semaphore模塊

sem = Semaphore(int數據類型)#可以指定有多少線程可以同時拿到鎖

sem.acquire()#需要上鎖將這些數據鎖住

sem.release()

事件Event模塊

e = Event()

e.wait()#根據is_set()的狀態來決定,自身的阻塞狀態 如果is_set()為False則為阻塞,如果is_set()為True則為非阻塞

e.is_set()#默認為False,

e.set()#將is_set()的狀態變為True

e.clear()#將is_set()的狀態變為False

典型例子:紅綠燈事件

3)進程間通信(IPC)

Queue模塊#隊列 先進先出 First in first out

q = Queue()#創建隊列對象(可以指定大小)

q.put() #向隊列中添加元素(如果隊列以滿處於阻塞狀態,只有當隊列不滿才可以繼續添加)

q.get()#取出隊列中元素(如果隊列中元素為空處於阻塞狀態,只有對列中有元素才可以繼續取出)

q.full()#判斷一個對列是否 已滿

q.empty()#判斷一個對列是否為空

q.put_nowait() #不阻塞,如果可以繼續往隊列中放數據就繼續放,不能放就報錯

q.get_nowait() #不阻塞,如果有數據就直接獲取,沒有數據就報錯

JoinableQueue()模塊

q = JoinableQueue()

#繼承了Queue模塊,但是新增了兩個方法

q.task_done() #統計對列q有多少個元素被拿走(拿走一個數據就給join返回一個結果),通常與q.get()在一起用 用於生產者

q.join()#感知一個對列的數據被全部執行完畢 與q.put()在一起用 用於消費著

隊列 = 管道 + 鎖

重點:生產者消費著模型

Pipe模塊#管道 (本身是不安全的) (雙全工)

p = Pipe()

conn1, conn2 = Pipe()

管道是不安全的

管道是用於多進程之間通信的一種方式

如果在單進程中使用管道,那麼就是conn1收數據,conn2發數據

如果是conn1發數據,那麼conn2收數據

如果在多進程中使用管道,那麼就必須是父進程中用con1收,子進程中使用conn2發

父進程使用conn1發,子進程中使用conn2收

父進程使用conn2收,子進程中使用conn1發

父進程使用conn2發,子進程中使用conn1收

在管道中有一個著名的錯誤叫做EOFERrror。

是指:父進程中如果關閉了發送端,子進程還繼續接受數據,那麼就會引發EOFError

4)數據共享Manager模塊 Value模塊

men = Manager()

(1)

m.list(列表數據)

m.dict(字典數據)

(2)

with Manager() as m:

……

5)進程池Pool模塊

p = Pool(os.cup_count() +1)#開啟多進程之後,每次處理數據只能指定個數個處理

p.close()

p.join()#close在join之前

方法:

map(func, itreable)#異步處理 itreable ,有返回值,返回值是,每一個func的返回值組成的列表, 自帶close和join

apply(func, argest)#同步處理有返回值,返回值為func的返回值 不需要加close和join

apply_async(func, argest, callback)#異步處理,有返回值,返回一個對象,這個對象有get方法,可以獲取func的返回值

#這個get只能一個一個獲取,以我們一般處理完所有線程後再獲取數據

#func的返回值可以作為參數傳給callback這個回調函數。回調函數在主進程中執行

apply函數中的所有進程都為普通進程

apply_async函數中的所有進程都為守護進程

線程學的東西:threading

GIL:全局解釋器鎖(只有CPython才有)

鎖的是線程:同一時間只允許一個線程訪問CPU #(沒有真正的並行)

1)Thread模塊

線程的創建

1)t = Thresd(target= func. argest = (元組,為func所傳的參數)) 實例化線程對象

2)繼承

多線程的創建

1)for 循環

2)直接實例化多個對象

2)鎖

Lock#互斥鎖(同步鎖)

RLock #遞歸鎖

死鎖#死鎖

信號量Semaphore模塊

sem = Semaphore(int數據類型)#可以指定有多少線程可以同時拿到鎖

sem.acquire()#需要上鎖將這些數據鎖住

sem.release()

事件Event模塊

e = Event()

e.wait()#根據is_set()的狀態來決定,自身的阻塞狀態 如果is_set()為False則為阻塞,如果is_set()為True則為非阻塞

e.is_set()#默認為False,

e.set()#將is_set()的狀態變為True

e.clear()#將is_set()的狀態變為False

3)條件Condition模塊

件是讓程序員自行去調度線程的一個機制

方法:

acquire()

release()

wait() #讓線程阻塞住

notify(int數據類型)#是指給wait發一個信號,讓wait變成不阻塞#int數據類型,是指你要給多少wai發信號

4)定時器Timer模塊

創建:Timer(time, func)

#time:睡眠時間,以秒為單位

#func:睡眠之後,需要執行的任務

5)線程池

進程與線程的區別:

進程資源分配的基本單位,線程是cpu調度的基本單位。

線程不可以自己獨立擁有資源。線程的執行,必須依賴於所屬進程中的資源。

進程中必須至少應該有一個線程。

線程和進程的比較:

1)cpu切換進程比切換線程慢很多,在python中如果IO操作過多的話,使用線程最好

2)在同一個進程內,所有線程共享這個進程pid,也就是說所有線程共享所屬進程的所有資源和內存地址

3)在同一個進程內,所有線程共享該進程中的全局變量

4)因為GIL鎖的存在,在CPython中,沒有真正的線程並行。但是有真正的多進程並行

當你的任務是計算密集的情況下,使用多進程好。

總結:在CPython中,IO密集用多線程,計算密集用多線程。

5)關於守護線程和守護進程的事情:(注意:代碼執行結束,並不代表程序結束)

守護進程:要麼自己正常結束,要麼根據父進程的代碼執行結束而結束

守護線程:要麼自己正常結束,要麼根據父線程的執行結束而結束(會等其餘子線程運行結束)

網絡編程+併發編程—總結


分享到:


相關文章: