1. 程式人生 > >假期(網絡編程)

假期(網絡編程)

str 組織 分類 toc 兩個 makefile 抽象層 客戶 分時

"""
一、客戶端/服務端架構:
    1、硬件C/S架構(打印機)
    2、軟件C/S架構
        互聯網中處處都是CS架構,服務端與客戶端
    CS架構與socket的關系
        - 我們學習socket就是為了完成C/S架構的開發

二、OSI七層模型:
    一個完整的計算機系統是由硬件、操作系統、應用軟件三者組成,一臺計算機只能自己玩自己,要想跟別人玩就需要上網了
    互聯網的核心就是由一堆協議組成,協議就是標準,比如全世界人通信的標準是英語;
    如果把計算機比做人,那麽互聯網協議就是計算機界的英語了,如果所有的計算機都學會了這門英語,那麽就可以互相通信了
    為何學習socket一定要先學習互聯網協議:
        - 1、首先我們的目標是基於socket編程,來開發一款自己的cs架構軟件
        - 2、其次cs架構軟件(軟件屬於應用層)是基於網絡進行通信的
        - 3、網絡的核心即一堆協議,協議即標準,你想開發一款基於網絡通信的軟件,就必須遵循這些標準

三、socket層
    socket層位於運輸層和應用層之間,即socket抽象層

四、socket是什麽?
    socket是應用層與TCP/IP協議族通信的中間軟件抽象層,它是一組接口。在設計模式中,socket其實就是一個門面模式,它吧復雜的
    TCP/IP協議族隱藏在了socket接口的後面,對用戶來說,一組簡單的接口就是全部,讓socket去組織數據,以符合指定的協議
    所以我們無需深入理解tcp/udp協議,socket已經幫我們封裝好了,我們只需要遵循socket的規定去編程,寫出的程序自然符合標準
    - 也有人將socket說成是IP+port,IP是用來標識互聯網中的一臺主機的位置,而port是用來標識這臺主機上的一個應用程序,IP地址
      配置到網卡上的,而port是應用程序開啟的,IP與port的綁定就標識了互聯網中獨一無二的應用程序
      程序的pid是同一臺機器上不同進程或者線程的標識

五、套接字的分類:
    - 基於文件類型的套接字家族
        套接字家族的名字:AF_UNIX
        unix一切皆文件,基於文件的套接字調用的就是底層文件系統來取數據,兩個套接字進程運行在同一機器,可以通過訪問同一個
        間接完成通信。
    - 基於網絡類型的套接字家族
        套接字家族的名字:AF_INET
        ···所有的地址家族中,AF_INET是使用最廣泛的一個,python支持很多種地址家族,但是由於我們只關心網絡編程,所以我們
        大部分時間都只是使用AF_INET

六、套接字的工作流程:
    一個生活中的場景:你要給你前對象打電話,先撥號,前對象聽到電話鈴聲後拿起電話,這時候你倆就建立起來了不正當的鏈接,然後
    就可以進行不正當的交易了。交易完成後,掛斷電話結束此次交談;
    先從服務端說起,服務端先初始化socket,然後與端口綁定(bind),對端口進行監聽(listen),調用accept阻塞,等待客戶端鏈接
    在這個時候如果有客戶端初始化一個socket,然後鏈接服務器(connect),如果鏈接成功,這時客戶端與服務端的鏈接就建立了。
    客戶端發送數據請求,服務端接收請求並處理,然後把回應數據發送給客戶端,客戶端讀取數據,關閉鏈接,交互結束
    - socket函數的用法
        import socket
        socket.socket(socket_family,socket_type,protocal=0)
        socket_family:可以是AF_UNIX或者是AF_INET;socket_type可以是SOCK_STREAM或SOCK_DGRAM,protocol一般默認為0

        獲取tcp/ip 套接字
        tcpsock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

        獲取udp/ip 套接字
        udpsock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

        由於socket模塊中有太多的屬性,我們直接在這裏使用 from xxx import * 的語句導入,這樣就可以減少代碼量
        eg:tcpsock = socket(AF_INET,SOCK_STREAM)
    - 服務端套接字函數
        s.bind()綁定(主機,端口號)到套接字
        s.listen()開始tcp監聽
        s.accept()被動接受tcp客戶的連接,(阻塞式)等待連接的到來
    - 客戶端套接字函數
        c.connect()被動初始化tcp服務器連接
        c.connect_ex() connect()函數的擴展版本,出錯時返回錯誤碼,而不是拋出異常
    - 公共用途的套接字函數
        s.recv()接受tcp數據
        s.send()發送tcp數據(send在待發送數據量大於已緩存區剩余的空間時,數據丟失,不會發完)
        s.sendall()發送完整的tcp數據(本質就是循環send,···數據不會丟失)
        s.recvfrom()接受udp數據
        s.sendto()發送udp數據
        s.getpeername()鏈接到當前套接字的遠程地址
        s.getsockname()當前套接字的地址
        s.getsockopt()返回指定套接字的參數
        s.setsockopt()設置指定套接字的參數
        s.close()關閉套接字鏈接
    - 面向鎖的套接字方法
        s.setblocking()設置套接字的阻塞與非阻塞模式
        s.settimeout()設置阻塞套接字操作的超時時間
        s.gettimeout()得到阻塞套接字操作的超時時間
    - 面向文件的套接字函數
        s.fileno()套接字的文件描述符
        s.makefile()創建一個與該套接字相關的文件
七、基於tcp的套接字
    tcp是基於鏈接的,必須先啟動服務端,然後再啟動客戶端去鏈接服務端
    - tcp服務端:
        server = socket()   #創建服務器套接字
        server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
        server.bind()       #把地址綁定到套接字
        server.listen()     #監聽鏈接
        while true:         #服務器無限循環
            client,addr = server.accept()    #接受客戶端鏈接
            while True:                 #通信循環
                client.recv()/client.send()   #接收與發送數據
            client.close()  #關閉客戶端套接字
        server.close()       #關閉服務器套接字
    - tcp客戶端:
        client = socket()    #創建客戶端套接字
        client.connect()     #嘗試鏈接服務器
        while True:
            client.send()/client.recv()   #發送/接收數據
        client.close()      #關閉客戶端套接字

八、基於udp的套接字
    - udp服務端
        server = socket()     #創建服務器套接字
        server.bind()         #綁定套接字地址
        while True:           #服務器無線循環
            client,addr = server.recvfrom()/server.sendto()    #接收與發送數據
        server.close()     #關閉服務器套接字
    - udp客戶端
        client = socket()      #創建客戶端套接字
        while True:            #通信循環
            client.sendto()/client.recvfrom()    #發送與接收數據
        client.close()  #關閉客戶端套接字

九、粘包現象(了解)
    如果當我們用socket模擬cmd執行遠程命令時,有些數據太長,超過了1024個字節,一次接受不完,就會造成粘包
    - 什麽是粘包?
        只有tcp才有粘包現象,udp永遠不會粘包,因為udp是基於流收發數據的
        所謂粘包的問題主要還是因為接收方不知道消息之間的界限,不知道一次性提取多少數據造成的
    - 粘包的解決
        - struct模塊
        - 自定義報頭
        - ···
    - 什麽時候才會發生粘包?
        發送端需要等緩沖區滿才發送出去,造成粘包(發送數據時間間隔很短,數據很小會喝到一起,產生粘包)
        接收方不及時接收緩沖區的包,造成多個包接收產生粘包
    - 了解
        tcp是可靠傳輸,udp是不可靠傳輸

十、socketserver模塊
    - 終極必殺技






















"""

假期(網絡編程)