網絡編程 與 併發編程 彙總

軟件開發架構:

C/S:
    Client: 客戶端
    Server: 服務端

    優勢:
        佔用網絡資源少,軟件的使用穩定

    缺點:
        服務端更新後,客戶端也得跟着跟新.
        須要使用多個軟件,須要下載多個客戶端

B/S:
    Browser: 瀏覽器(客戶端)
    Server: 服務端

服務端與客戶端做用:
    服務端: 24小時不間斷提供服務
    客戶端: 須要體驗服務端時,再去鏈接服務端,並享受服務

一 網絡編程:
1.互聯網協議OSI七層協議
    1)應用層
    2)表示層
    3)會話層
    4)傳輸層
    5)網絡層
    6)數據鏈路層
    7)物理鏈接層

    - 物理鏈接層
        基於電信號發送二進制數據.

    - 數據鏈路層
        1) 規定好電信號的分組方式
        2) 必需要有一塊網卡:
            - mac地址:
                12位惟一的16進制字符串
                    - 前6位: 廠商號
                    - 後6位: 流水號
        - 以太網協議:
            在同一個局域網內通訊.
            - 單播
                1對1吼
            - 廣播
                多對多吼
                - 廣播風暴:
                - 不能跨局域網通訊

    - 網絡層
        - ip: 定位局域網的位置
        - port: 惟一標識一臺計算機上一個應用程序.
        - arp協議:
            將mac地址獲取,並解析成ip和port.

    - 傳輸層
        - TCP
            特色:
                TCP協議稱之爲流式協議.

            若想要通訊,必須創建鏈接,並創建雙向通道.
            - 三次握手,四次揮手
                - 三次握手建鏈接
                    - 客戶端往服務端發送請求創建通道
                    - 服務端要確認客戶端的請求,並往客戶端也發送請求創建通道
                    - 客戶端接收到服務端創建鏈接的請求,並返回確認
                    - 創建雙向通道

                - 雙向通道:
                    - 反饋機制
                    客戶端往服務端發送請求獲取數據,服務端務必返回數據,客戶端確認收到.
                    反則會反覆發送,一直到某個時間段內,會中止發送

                - 四次揮手斷鏈接
                    - C往S發送斷開鏈接請求,S返回確認收到
                    - S須要再次發送斷開鏈接請求
                    - C返回確認收到
                    - 最終確認斷開鏈接

        - UDP
            1)數據不安全
            2)不須要創建雙向通道
            3)傳輸速度快
            4)不會有粘包問題
            5)客戶端發送數據,不須要服務端確認收到,愛收不收

        TCP與UPD的區別:
            TCP: 比喻成在打電話
            UDP: 比喻成發送短信

    - 應用層
        - ftp
        - http:
            能夠攜帶一堆數據

        - http + ssl

2.socket
    socket用來寫套接字客戶端與服務端的模塊,內部幫咱們封裝好了7層協議須要作的事情.

3.手擼socket套接字模板
    - 服務端:
        import socket
        server = socket.socket()
        server.bind(
            (ip, port)
        )  # 綁定手機號
        server.listen(6)  # 半鏈接池: 能夠接待7個客戶端
        # 監聽鏈接
        conn, addr =server.accept()
        # 接收消息
        data = conn.recv(1024)
        # 發送消息
        conn.send('消息內容'.encode('utf-8'))

    - 客戶端:
        import socket
        client = socket.socket()
        client.connect(
            (ip, port)
        )
        # 發送消息
        client.send()
        # 接收消息
        client.recv(1024)

4.subprocess(瞭解)
    用來經過代碼往cmd建立一個管道,而且發送命令和接收cmd返回的結果.
    import subprocess
    obj = subprocess.Popen(
        'cmd命令',
        shell=True,
        # 接收正確結果
        stdout=subprocess.PIPE,
        # 接收錯誤結果
        stderr=subprocess.PIPE
    )
    success = obj.stdout.read()
    error = obj.stderr.read()
    msg = success + error


5.黏包問題
    1.不能肯定對方發送數據的大小
    2.在短期內,間隔時間短,而且數據量小的狀況, 默認將這些數據打包成一個
        屢次發送的數據 ---> 一次性發送

6.struct解決黏包問題
    初級版:
    i: 4
    能夠將一個數據的長度打包成一個固定長度的報頭.
    struct.pack('模式i', '源數據長度')
    data = 'gagawagwaga'
    # 打包成報頭
    headers = struct.pack('i', len(data))

    # 解包獲取數據真實長度
    data = struct.unpack('i', headers)[0]

    注意: 以什麼方式打包,必須以什麼方式解包.

    升級版:
        先將數據存放到字典中,將字典打包發送過去
        - 字典的好處:
            - 真實數據長度
            - 文件的描述信息
            - 發送的數據,更小

            dic = {
                'data_len': 1000000000000000000000046546544444444444444444444444444444444444444,
                文件的描述信息
            }

7.上傳大文件數據
    # 客戶端
    dic = {
            文件大小,
            文件名
           }

    with open(文件名, 'rb') as f:
        for line in f:
            client.send(line)


    # 服務端
    dic = {
            文件大小,
            文件名
           }
    init_recv = 0
    with open(文件名, 'wb') as f:
        while init_recv < 文件大小:
            data = conn.recv(1024)
            f.write(data)
            init_recv += len(data)


10.socketserver(現階段,瞭解)
    - 能夠支持併發
    import socketserver
    # 定義類
    # TCP: 必須繼承BaseRequestHandler類
    class MyTcpServer(socketserver.BaseRequestHandler):

        - handle
            # 內部實現了
            server = socket.socket()
            server.bind(
                ('127.0.0.1', 9527)
            )
            server.listen(5)  ---

            while True:
                conn, addr = server.accept()
                print(addr)

        # 必須重寫父類的handle, 當客戶端鏈接時會調用該方法
        def handle(self):
            print(self.client_address)
            while True:
                try:
                    # 1.接收消息
                    # request.recv(1024) == conn.recv(1024)
                    data = self.request.recv(1024).decode('utf-8')
                    send_msg = data.upper()
                    self.request.send(send_msg.encode('utf-8'))

                except Exception as e:
                    print(e)
                    break
    TCP:
        SOCK_STREAM
        conn.recv()

    UDP模板:
        SOCK_DGRAM
        server.recvfrom()

        - 服務端
            import socket
            server = socket.socket(
                type=socket.SOCK_DGRAM
            )
            server.bind(
                (ip, port)
            )
            data, addr = server.recvfrom(1024)
            server.sendto(data, addr)

        - 客戶端
            import socket
            client = socket.socket(
                type=socket.SOCK_DGRAM
            )
            ip_port = (ip, port)

            client.sendto(data, ip_port)

            data, _ = client.recvfrom(1024)
            print(data)


二 併發編程

12.多道技術
    - 單道

    - 多道: 切換 + 保存狀態
        - 空間上的複用
            支持多個程序使用

        - 時間上的複用
            - 遇到IO操做就會切換程序
            - 程序佔用CPU時間過長切換

13.併發與並行
    併發: 看起來像同時運行: 多道技術
    並行: 真正意義上的同時運行: 多核下


14.進程
    進程是資源單位,沒建立一個進程都會生成一個名稱空間,佔用內存資源.

    - 程序與進程
          程序就是一堆代碼
          進程就是一堆代碼運行的過程

  - 進程調度
        - 時間片輪轉法
            10個進程, 將固定時間,等分紅10份時間片,分配給每個進程.

        - 分級反饋隊列
            1級別:
            2級別:
            3級別:


  - 進程的三個狀態
        - 就緒態:
            建立多個進程, 必需要排隊準備運行

        - 運行態:
            進程開始運行, 1.結束  2.阻塞

        - 阻塞態:
            當運行態遇到IO操做,就會進阻塞態.

  - 同步與異步
        提交任務的方式
        - 同步: 同步提交, 串行,一個任務結束後,另外一個任務才能提交併執行.
        - 異步: 異步提交, 多個任務能夠併發運行

  - 阻塞與非阻塞
    - 阻塞:
        阻塞態
    - 非阻塞:
        就緒態
        運行態

  - 同步和異步、阻塞和非阻塞的區別。
        二者是不一樣的概念,不能混爲一談.

  - 建立進程的兩種方式
        一:
            p = Process(target=任務, args=(任務的參數, ))
            p.daemon = True  # 必須放在start()前,不然報錯
            p.start()  # 向操做系統提交建立進程的任務
            p.join()  # 向操做系統發送請求, 等全部子進程結束,父進程再結束

        二:
            class MyProcess(Process):
                def run(self):  # self == p
                    任務的過程

            p = MyProcess()
            p.daemon = True  # 必須放在start()前,不然報錯
            p.start()  # 向操做系統提交建立進程的任務
            p.join()  # 向操做系統發送請求, 等全部子進程結束,父進程再結束


  - 回收進程資源的兩種條件
        - 調用join讓子結束後,主進程才能結束.
        - 主進程正常結束

15.殭屍進程與孤兒進程(瞭解)
    殭屍進程: 凡是子進程結束後,PID號還在, 主進程意外死亡,無法給子進程回收資源.
        - 每一個子進程結束後,都會變成,殭屍進程 (PID)

    孤兒進程: 凡是子進程沒有結束,可是主進程意外死亡.操做系統優化機制(孤兒院),
    會將沒有主,而且存活的進程,在該進程結束後回收資源.

16.守護進程
    只要父進程結束,全部的子進程都必須結束.

17.互斥鎖
    將併發變成串行,犧牲執行效率,保證數據安全.

    from multiprocessing import Lock
    mutex = Lock()
    # 加鎖
    mutex.acquire()
    修改數據
    mutex.release()

18.隊列
    - FIFO隊列: 先進先出
    from multiprocessing import Queue
    q = Queue(5)
    # 添加數據,若隊列添加數據滿了,則等待
    q.put()
    # 添加數據,若隊列添加數據滿了,直接報錯
    q.put_nowait()

    # 獲取隊列中的數據
    q.get()  # 若隊列中沒數據,會卡住等待
    q.get_nowait()  # 若隊列中沒數據,會直接報錯

19.堆棧
    LIFO

20.IPC進程間通訊
    - 進程間的數據是隔離的
    - 隊列可讓進程間通訊
    - 把一個程序放入隊列中,另外一個程序從隊列中獲取,實現進程間數據交互


21.生產者與消費者 模型
    生產者: 生產數據
    消費者: 使用數據
    爲了保證 供需平衡.

    經過隊列實現, 生產者將數據扔進隊列中,消費者從隊列中獲取數據.
        能夠保證一邊生產一邊消費.



22.線程
    - 什麼是線程
        - 進程: 資源單位
        - 線程: 執行單位
            - 建立進程時,會自帶一個線程

        一個進程下能夠建立多個線程.

    - 使用線程的好處
        節省資源的開銷

    - 進程與線程優缺點:
        - 進程:
            優勢:
                - 多核下能夠並行執行
                - 計算密集型下提升效率

            缺點:
                - 開銷資源遠高於線程

        - 線程:
            優勢:
                - 佔用資源遠比進程小
                - IO密集型下提升效率

            缺點:
                - 沒法利用多核優點


23.線程間數據是共享的
    - 畫圖

24.GIL全局解釋器鎖

    - 只有Cpython纔有自帶一個GIL全局解釋器鎖
    1.GIL本質上是一個互斥鎖.
    2.GIL的爲了阻止同一個進程內多個線程同時執行(並行)
        - 單個進程下的多個線程沒法實現並行,但能實現併發

    3.這把鎖主要是由於CPython的內存管理不是 "線程安全" 的.
        - 內存管理
            - 垃圾回收機制

            注意: 多個線程過來執行,一旦遇到IO操做,就會立馬釋放GIL解釋器鎖,交給下一個先進來的線程.

    總結: GIL的存在就是爲了保證線程安全的,保證數據安全

25.多線程使用的好處
    - 多線程:
        IO密集型,提升效率

    - 多進程
        計算密集型,提升效率

26.死鎖現象(瞭解)

27.遞歸鎖(瞭解,之後不用)
    解決死鎖現象
    mutex = Lock()  # 只能引用1次
    mutex1, mutex2 = RLock()  # 能夠引用屢次
    +1, 只要這把鎖計數爲0釋放該鎖, 讓下一我的使用, 就不會出現死鎖現象.

28.信號量(絕對了解)
    信號量也是一把鎖, 可讓多個任務一塊兒使用.
    互斥鎖:
        只能讓一個任務使用
    信號量:
        可讓多個任務一塊兒使用.
        sm = Semaphore(5)  可讓5個任務使用

29.線程隊列
    使用場景:
        若線程間數據不安全狀況下使用線程隊列, 爲了保證線程間數據的安全.
    import queue
    - FIFO: 先進先出隊列
        queue.Queue()
    - LIFO: 後進先出隊列
        queue.LifoQueue()
    - 優先級隊列:
        - 根據數字大小判斷,判斷出隊優先級.
        - 進隊數據是無序的
        queue.PriorityQueue()

30.event事件
    能夠控制線程的執行,讓一些線程控制另外一些線程的執行.
    e = Event()

    - 線程1
    e.set()  # 給線程2發送信號,讓他執行

    - 線程2
    e.wait()  # 等待線程1的信號

31.進程池與線程池
    爲了控制進程/線程建立的數量,保證了硬件能正常運行.
    from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor

    pool1 = ProcessPoolExecutor()  # 默認CPU個數
    pool2 = ThreadPoolExecutor()  # CPU個數 * 5
    pool3 = ProcessPoolExecutor(100)  # 100個
    pool4 = ThreadPoolExecutor(200)  # 200個

    # 將函數地址的執行結果,給回調函數
    pool4.submit(函數地址, 參數).add_done_callback(回調函數地址)

    - 回調函數(必須接收一個參數res):
        # 獲取值
        res2 = res.result()

32.協程
    - 進程: 資源單位
    - 線程: 執行單位
    - 協程: 單線程下實現併發, 不是任何的單位,是程序員YY出來的名字.

    - 單線程下實現併發
        好處是節省資源, 單線程 < 多線程 < 多進程

        - IO密集型下:
            協程有優點

        - 計算密集型下:
            進程有優點

    - 高併發:
        - 多進程 + 多線程 + 協程   (Nginx)

    協程的建立:
        手動實現切換 + 保存狀態:
            - yield

            - 函數一直在調用next()
                會不停地切換

            yield不能監聽IO操做的任務
            - gevent來實現監聽IO操做

33.gevent
    pip3 install gevent
    from gevent import monkey
    monkey.patch_all()  # 設置監聽全部IO
    from gevent import spawn, joinall  # 實現 切換 + 保存狀態

    - 實現了單線程下實現併發
    s1 = spawn(任務1)
    s2 = spawn(任務2)
    joinall([s1, s2])

34.IO模型(瞭解)
    - 阻塞IO
    - 非阻塞IO
    - 多路複用IO
    - 異步IO
相關文章
相關標籤/搜索