Python網路程式設計(基礎總結入門經典)

巴黎香榭發表於2018-08-18
Linux下檔案型別:
    bcd -lsp
         b(塊、裝置檔案)
         c(字元裝置檔案)
         d(目錄)
         -(普通檔案)
         l(連結檔案)
         s(套接字檔案)
         p(管道檔案)
    kill -sig pid:通過pid傳送訊號殺死指定程式
    kill -l:檢視作業系統內所所有sig訊號
    ps -aux —> STAT表示程式狀態
    訊號:
        SIGHUP   斷開連結
    SIGINT   Ctrl + c
    SIGQUIT  Ctrl +
    SIGTSTP  Ctrl + z
    SIGKILL  終止程式且不能被處理
    SIGSTOP  暫停程式且不能被處理
    SIGALRM  時鐘訊號
    SIGCHLD  子程式改變狀態時父程式會收到此訊號
OSI七層模型 —–> 網路通訊的標準化流程
    應用層: 提供使用者服務,具體的內容由特定的程式規定
    表示層: 提供資料的加密和壓縮優化
    會話層: 確定建立應用連結,選擇傳輸服務
    傳輸層: 提供資料傳輸服務,進行流量控制
    網路層: 路由選著,網路互聯
    鏈路層: 提供鏈路交換,具體訊息的傳送
    物理層: 物理硬體,介面,網路卡的規定
網路協議:
應用層:TFTP(檔案傳輸)、HTTP(超文字傳輸協議)、DNS(域名解析)、SMTP(郵件傳輸)
傳輸層:TCP、UDP
網路層:IP
物理層:IEEE
IP地址
本地使用:127.0.0.1 或 “localhost”
網路地址:“0.0.0.0” 或 “172.168.40.53”
IPv4: 點分十進位制   例如:192.168.1.3   取值0~255(32位)
IPv6: 128位
socket模組:
    ifconfig:檢視本機IP (ens33:本地IP  lo:本地回還)
    ipconfig:windoes中
    socket.gethostname() :                        獲取本機主機名
    socket.gethostbyname(`tedu`) :                利用主機名獲取ip
    socket.gethostbyname(`localhost`):    獲取本地ip
    socket.gethostbyaddr(`127.0.0.1`)      訪問主機IP地址
    socket.inet_aton(`192.168.1.2`)        IP十六進位制轉換
    socket.inet_ntoa(b`xc0xa8x01 2`)  IP十進位制轉換
    socket.getservbyname(`ssh`)            獲取應用程式的埠
建立TCP服務端套接字:
sockfd.socket(sock_family = AF_INET,
               sock_tpye = SOCK_STREAM,
               proto = 0)
    sockfd.bind(addr)      繫結地址
    sockfd.listen(n)          設定監聽套接字
  connfd,addr = sockfd.accept() 等待接受客戶端連結
  data = connfd.recv(buffersize) 接收訊息
  connfd.send(data) 傳送訊息
  sockfd.close() 關閉套接字
建立TCP客戶端套接字:
sockfd.socket(sock_family = AF_INET,
               sock_tpye = SOCK_STREAM,
               proto = 0)
    sockfd.bind(addr)      繫結地址
  sockfd.connect(addr) 連結服務端
  data = connfd.recv(buffersize) 接收訊息
  connfd.send(data) 傳送訊息
  sockfd.close() 關閉套接字

建立UDP客戶端套接字:
  sockfd.socket(sock_family = AF_INET,
               sock_tpye = SOCK_DGRAM,
               proto = 0)
    sockfd.bind(addr)      繫結地址
  data = sockfd.recvfrom(buffersize) 接收訊息
  sockfd.sendto(data, addr) 傳送訊息
  sockfd.close() 關閉套接字
建立UDP客戶端套接字:
  sockfd.socket(sock_family = AF_INET,
               sock_tpye = SOCK_DGRAM,
               proto = 0)
  data = sockfd.recvfrom(buffersize) 接收訊息
  sockfd.sendto(data, addr) 傳送訊息
  sockfd.close() 關閉套接字

建立本地套接字服務端:
  sockfd = socket(AF_UNIX, SOCK_STREAM) 建立本地套接字物件
  sockfd.bind(file) 繫結套接字檔案
  sockfd.listen(3) 監聽
  connfd,addr = sockfd.accept() 等待連結
  connfd.recv(buffersize) 接收訊息
  connfd.send(data) 傳送訊息
  sockfd.close() 關閉套接字
建立本地套接字客戶端:
  sockfd = socket(AF_UNIX, SOCK_STREAM) 建立本地套接字物件
  sockfd.connect(sock_file) 連結服務端
  connfd.recv(buffersize) 接收訊息
  connfd.send(data) 傳送訊息
  sockfd.close() 關閉套接字
套接字屬性:
  sockfd.type 返回套接字型別
  sockfd.family 返回地址型別
套接字方法:
  sockfd.fileno() 獲取套接字的檔案描述符
  sockfd.getsockname() 獲取套結字繫結的地址
  sockfd.getpeername() 獲取連結套接字客戶端的地址
  sockfd.setsockopt(level,optname, value) 設定埠可立即重用
  sockfd.setblocking(False) 將套接字設定為非阻塞狀態
  sockfd.settimeout(sec) 設定套接字的超時時間

select模組: IO多路複用,阻塞等待監控的IO事件發生
rs, ws, xs = select(rlist, 等待處理的IO
  wlist 想要主動處理的IO
  xlist[, 出錯希望去處理的IO
  timeout]) 超時檢測
p = select.poll 建立poll物件
p.register(s, POLLIN | PLLERR) 註冊關注的IO
events = p.poll() 監控關注的IO事件
multiprocessing模組: 建立程式物件
Process(target, 要繫結的函式
name, 給程式起的名稱
args, 元組給target函式位置傳參
kwargs) 字典給target函式鍵值傳參
p.start() 啟動程式terget繫結函式
p.join([timeout]) 阻塞等待子程式退出
p.name                        獲取程式名(屬性)
p.daemon 設定為True主程式結束殺死所有子程式(必須start()前設定)
p.is_alive() 判斷程式是處於alive狀態(存活)
p.pid 獲取建立程式的pid號(屬性)
pool = pool(x) 建立程式池物件(程式池大小)
pool.apply_async(fun, 要執行的函式(非同步執行)
args, 以元組形式為fun傳參
kwds) 以字典形式為fun傳參
pool.apply(fun, args, kwds) (同步執行)
r = pool.map(fun,range(6)) 將要執行的事件放入程式池
pool.close() 關閉程式池
pool.join() 回收程式池
fd1,fd2 = Pipe(duplex=True) 建立管道(Flase:fd1只讀,fd2只寫)
fd.recv() 從管道讀取資訊空則阻塞
fd.send(data) 向管道寫入內容滿則阻塞
q = Queue(maxsize=0) 建立佇列物件(存放多少條訊息)
q.put(data, 存入訊息(支援Python資料型別)
   [block, 預設阻塞 False:非阻塞
   timeout]) block為True是表示超時檢測
data = q.get([block,timeout]) 取出訊息
q.full() 判斷佇列是否為滿
q.empty()    判斷佇列是否為空
q.qsize()    獲取佇列中訊息的數量
q.close()    關閉佇列
shm = Value(ctype, 建立共享記憶體共享空間
obj) ctype字串:(C語言資料型別),obj初始資料
shm.value 表示共享記憶體的值(可以賦值)
shm = Array(ctype,obj) 建立共享記憶體共享空間
sem = Semaphore(num) 建立訊號量
sem.acquire() 將訊號量減1  0時阻塞
sem.release() 將訊號量加1
sem.get_value() 獲取當前訊號量的值(數量)
e = Event() 建立Event事件物件
e.wait([timeout]) 阻塞程式 直到事件物件被set
e.set.() 讓事件物件變為被設定狀態
e.clear() 使事件物件清除設定狀態
e.is_set() 判斷當前事件是否被set
Lock = Lock() 建立鎖物件
lock.acquire() 上鎖
lock.release() 解鎖
threading 模組: 建立執行緒物件
threshold.Thread(target, 執行緒函式
  name, 執行緒名字
  args, 元組給執行緒函式位置傳參
  kwargs) 字典給執行緒函式位置傳參
t.start() 啟動執行緒
t.join()  回收執行緒
t.name 執行緒名
t.daemon = True 主執行緒退出分支執行緒也退出
t.setDaemon(True) 主執行緒退出分支執行緒也退出
t.isDaemon 檢視daemon值
t.setName(“name”) 設定執行緒名稱
t.is_alive() 檢視執行緒狀態
threading.currentThread() 獲取當前程式物件
e = threading.Event() 建立Event事件物件
e.wait([timeout]) 事件阻塞
e.set() 設定事件
e.clear() 清除事件
lock = threading.Lock() 建立鎖物件
lock.acquire() 上鎖
lock.release() 解鎖
socketserver整合併發模組:
StreamRequestHandler    處理tcp請求
DatagramRequestHandler  處理udp請求
ForkingMixIn    建立多程式
ThreadingMixIn  建立多執行緒
 
TCPServer  建立tcp  server
UDPServer  建立udp  server
ForkingTCPServer      ForkingMixIn  +  TCPServer 
ForkingUDPServer      ForkingMixIn  +  UDPServer 
ThreadingTCPServer    ThreadingMixIn  +  TCPServer 
ThreadingUDPServer    ThreadingMixIn  +  UDPServer 
signal模組:
signal.alarm(sec) 設定時鐘訊號給自己SIGALRM訊號
signal.pause() 阻塞程式,等待一個訊號
signal.signal(sig, 要處理的訊號
   handler) 處理方法(SIG_DFL:預設 SIG_IGN:忽略 func:自定義函式)
sys模組補充:
    sys.argv 獲取從命令列獲取的引數內容列表
    sys.stdin    0 標準輸入IO檔案描述符
    sys.stdout   1 標準輸出IO檔案描述符
    sys.stderr   2 錯誤IO檔案描述符
    sys.exit([status])                        退出一個程式(狀態:退出提示字串)
字串方法補充:
    S.splitlines  按行分隔
os模組補充:
os.path.exists(file) 判斷一個檔案是否存在
os.remove(file) 刪除檔案
os.unlink(file) 刪除檔案
pid = os.fork() 建立程式 失敗-1 成功0
os.getpid() 獲取程式的PID號
os.getppid() 獲取父程式的PID
os.exit(status) 退出一個程式(狀態:整數 預設0)
pid,status = os.wait() 塞等待處理子程式的退出
os.WEXITSTATUS(status) 獲取原來退出狀態
pid,status = os.waitpid(pid,option) 阻塞等待處理子程式的退出
os.path.getsize(`./1.txt`)                   讀取檔案的大小
os.kill(pid,sig) 傳送一個訊號給某個程式
os.listdir(path) 獲取指定目錄檔案列表
os.path.isfile()  判斷一個 檔案是否為普通檔案
os.path.isdir()  判斷一個檔案是否為目錄 
傳輸層服務:
    面向連線的傳輸服務(tcp協議):
        傳輸特徵:
          可靠的資料傳輸:
            可靠性:無失序、無差錯、無重複、無丟失、無重複
        在資料傳輸前和傳輸後需要建立連線和斷開連結
          面向傳輸服務建立連線的過程:‘三次握手’
            1.客戶端向伺服器傳送連結請求
            2.伺服器接受到請求進行確認,返回確認報文
            3.客戶端收到伺服器回覆最終確認連結
          面向傳輸服務斷開連結的過程:‘四次揮手’
            1.主動方傳送報文,告知被動方要斷開連結
    2.被動方回覆報文,表示已經接受到請求,準備斷開
    3.被動方再次傳送報文,表示準備處理就緒,可以斷開
    4.主動方傳送確認報文,斷開連結
        應用情況:
    適用於傳輸較大的內容或檔案,網路良好,
    需要保證傳輸可靠性的情況
    e.g.  資訊聊天,檔案上傳下載,郵件,網頁獲取
    面向無連線的傳輸服務(udp協議):
        不保證傳輸的可靠性
沒有建立連線和斷開的過程
資料的收發比較自由
適用情況: 
    網路情況較差,對可靠性要求不高,收發訊息的兩端
    e.g.:網路視訊,群聊,廣播等
收發函式特性:
     recv特徵:
       如果建立的另一端連結被斷開, 則recv立即返回空字串
       recv是從接受緩衝區取出內容,當緩衝區為空則阻塞
       recv如果一次接受不完緩衝區的內容,下次執行會自動接受
     send特徵:
        如果傳送的另一端不存在則會產生pipe…異常
send是從傳送緩衝區傳送內容當緩衝區為滿則堵塞
http協議:
   超文字傳輸協議
   用途:
      網站中瀏覽區器網頁的獲取,基於網站事物資料傳輸
      編寫基於http協議的資料傳輸
   特點:
      1.應用層協議,傳輸層使用tcp服務
      2.簡單、靈活,可以使用多種程式語言操作
      3.無狀態的協議,既不用記錄使用者的輸入內容
      4.http1.1  —> http2.0(還沒釋出)  技術的成熟和穩定性
   http請求(request):
      1.請求格式:
         1)請求行:說明具體的請求類別和內容
          GET    /index.html    /HTTP/1.1
                請求類別   請求內容    協議版本
     2)請求類別:
        GET:獲取網路資源
POST:提交一定的附加資料
HEAD:獲取相應頭
PUT:更新伺服器資源
DELETE:刪除伺服器資源
CONNECT:未使用
TRACE:用於測試
OPTIONS:獲取伺服器效能資訊
2.請求頭:對請求的具體描述
     Accept:text/html
        每一個鍵值對佔一行,描述了一個特定資訊
3.空行
4.請求體:具體的引數或提交的內容
          get引數或者post提交的內容
   http響應(response):
      1.響應格式:
        1)響應行:反饋具體的響應情況
          HTTP/1.1     20       OK
  版本協議   響應碼   附加資訊
    3)響應碼:
       1xx:提示資訊,表示請求已經接收
       2xx:響應成功
       3xx:響應需要定向
       4xx:客戶端錯誤
       5xx:伺服器端錯誤
3)常見響應碼:
   200  成功
   404  請求內容不存在
   401  沒有訪問許可權
   500  伺服器未知錯誤
       503  伺服器暫時無法執行
      2.響應頭:對響應內容的具體描述
      3.空行
      4.響應體:
         將客戶端請求內容進行返回
IO多路複用
定義:
通過一個監測,可以同時監控多個IO事件的行為,
當那個IO可以執行,讓這個IO事件發生
同時監控多個IO事件,當哪個IO事件準備就緒就執行哪個IO事件
此時形成多個IO時間都可以操作的現象,不必逐個等待執行
IO準備就緒:
IO事件即將發生時的臨界狀態是不可逆轉的
在程式中存在的IO事件中選擇要監測的事件
建立監測,將監測的IO事件註冊
等待監測的IO事件發生,判斷是什麼事件
處理相應的IO
poll方法實現IO多路複用:
   1.建立poll物件:
       p = select.poll
   2.註冊關注的IO:
       p.register(s, POLLIN | PLLERR)
       不關注:
          p.unregister(s)
       事件類別:
          POLLIN  POLLOUT  POLLERR  POLLHUP   POLLPRI
          rlist    wlist    xlist     斷開   緊急處理 
   3.監控IO:
       events = p.poll()
       功能:監控關注的IO事件
       返回值:
           返回發生IO事件
   events是一個列表[(fileno, evnet), (), ()….]
   每個就緒IO對應一個元組(描述符,就緒事件)
       IO地圖:{s.fileno():s}
   4.處理IO事件
位運算:
   按照二進位制位進行位運算操作
   & 按為與   |按位或   ^按位異或
   << 左異    >>右移
   11  1011
   14  1110
   &   1010  有0得0
   |   1111  有1得1
   ^   0101  相同為0不同為1
  
   11 << 2  == 44   右側補零(乘2乘2次)
   14 >> 2  == 3    擠掉右側的數字(地板除2除2次)
使用:
    1.在低層硬體時操作暫存器
    2.做標誌位的過濾
多工程式設計:
    意義:
充分利用計算機資源,同時執行多個任務,
提高程式整體的執行效率
    定義:
通過程式利用計算機的多個核心達到同時執行多個任務的目的
因此達到提升程式執行效率的目的
    實施方案:
多程式程式設計
多執行緒程式設計
    並行:
        多個計算機核心在同時處理多個任務,
這時多個任務之間是並行關係
     併發:
        同時執行多個任務,核心在多個任務之間的不斷切換,
達到多個任務都會執行的處理效果
此時多個任務之間的併發關係

程式:
    是一個可執行檔案,是靜態的,只佔有磁碟
    不佔用計算機執行資源
程式:
    程式在計算機中的一次執行過程
    是一個動態過程,佔有一定的計算機資源
    有一定的生命週期
注:
    同一個程式不同的執行過程是不同的程式,
    因為分配的資源和生命週期都不同
程式的建立過程:
    1.使用者啟動一個程式,或是呼叫介面發起程式建立
    2.作業系統接收使用者請求分配計算機資源建立程式
    3.作業系統將一定狀態的程式提供給使用者使用
    4.使用者利用操作提供的程式完成任務

CPU時間片:
    如果有個程式佔有CPU此時我們稱為該程式佔有CPU的時間片
    多個程式任務或輪流佔有CPU時間片並形成併發效果
  
程式資訊(process)
    PCB(程式控制塊):
         程式建立後 會自動在記憶體中產生一個空間存放程式資訊
    程式資訊:
        程式ID 程式佔有記憶體的位置  建立時間、建立位置
檢視系統程式資訊:ps -aux
    PID(process ID):
      在作業系統中每個程式都有唯一的PID值是由系統分配的
程式特徵:
    程式是作業系統分配資源的最小單元
    每個程式擁有自己獨立的執行空間(4個G的虛擬記憶體空間)
    程式之間相互獨立各不影響
程式的狀態:
    三態:
    就緒狀態:
         程式具備執行條件,等待系統分配處理器資源進入執行態
    執行態:
         程式佔有CPU處於執行狀態
    等待態:
         程式暫時不具備執行條件,需要阻塞等待
    五態:
         在三態的基礎上增加新建和終止態 
新建:
   建立一個新的程式,獲取系統資源的過程
終止:
   程式執行結束,釋放資源的過程
ps -aux —> STAT表示程式狀態:
    D  等待態  阻塞  不可中斷等待態
    S  等待態  睡眠  可中斷等待態
    T  等待態  暫停  暫停執行
    R  執行態(就緒態)
    Z  殭屍
      +  前臺程式(在終端執行)
      <  有較高優先順序的程式
      N  較低優先順序的程式
      s  回話組
      l  有程式連結
程式的優先順序:
    top 檢視程式執行態優先順序
    取值範圍:-20~19   -20最高
    nice:
       以指定的優先順序執行一個程式
       nice -9 ./hello.py  以9的優先順序執行
       sudo nice –9 ./hello.py 以-9優先順序執行
    首行新增 #! /usr/bin/python3  指定執行器
      執行:./hello.py
    修改程式許可權新增可執行許可權
         chmod 775 hello.py

孤兒程式 : 
當父程式先於子程式退出,此時子程式就會成為孤兒程式。
    * 孤兒程式會被系統指定程式收養,即系統程式會成為孤兒
      程式新的父程式。系統程式會自動處理孤兒程式退出狀態

殭屍程式 : 
子程式先於父程式退出,父程式沒有處理子程式的退出狀態,此時子程式就會成為殭屍程式
* 殭屍程式會滯留部分PCB資訊在記憶體中,大量的殭屍進
  程會消耗系統的記憶體資源,所以要儘量避免殭屍程式產生
如何避免殭屍程式產生?
* 父程式先退出
* 父程式處理子程式退出狀態
* 建立二級子程式
程式池技術:
    產生原因:
    如果有大量的任務需要多程式完成,而呼叫週期比較短且需要頻繁建立
此時可能產生大量程式頻繁建立銷燬的情況  消耗計算機資源較大
    使用方法:
    1.建立程式池,在池內放入適當數量的程式
2.將事件封裝成函式。放入到程式池
3.事件不斷執行,直到所有放入程式池事件執行完成
4.關閉程式池,回收程式
同步互斥機制
    目的:
       解決對共有資源產生的資源爭奪
    臨界資源:
         多個程式或執行緒都可以操作的資源
    臨界區:
        操作臨界資源的程式碼段
    同步:
    同步是一種合作關係,為完成某個任務,
多程式或者多個執行緒之間形成的一種協調
按照約定執行,相互告知,共同完成任務
    互斥:
    互斥是一種制約關係,當一個程式或者執行緒
進入臨界區操作資源時採用上鎖的方式,
阻止其他程式操作,直到解鎖後才能讓出資源
多執行緒:
    什麼是執行緒(thread)?
      執行緒也是一種多工程式設計方式,可以使用計算機的多核資源
      執行緒被稱為輕量級的程式
    執行緒的特徵:
      1.一個程式可以包含多個執行緒
      2.執行緒是計算機核心使用的最小單位
      3.執行緒也是一個執行過程,也要消耗計算機資源
      4.多個執行緒共享共用程式的資源
      5.執行緒也有自己的特徵屬性,TID、指令集、執行緒棧
      6.多個執行緒之間獨立執行互不干擾 空間不獨立(都消耗程式空間)
      7.執行緒的建立刪除消耗的資源要小於程式 執行緒/程式(1/20)
執行緒通訊:
               多個執行緒共用執行緒空間,所以程式的全域性變數對程式內執行緒均可見
               執行緒的通訊方法就是使用去全域性變數通訊
       注:
              執行緒間使用全域性變數程式通訊時,全域性變數為共享資源
               往往需要同步互斥機制
程式和執行緒的區別和聯絡:
    1.兩者都是多工程式設計的方式  都能夠使用計算機的多核
    2.程式的建立和刪除要比執行緒消耗更多的計算機資源
    3.程式空間獨立,資料安全性好,有專門的程式間的通訊方法
    4.執行緒使用全域性變數,更加簡單,但需要同步互斥操作
    5.一個程式可以包含多個執行緒,執行緒共享程式空間資源
    6.程式執行緒都獨立執行,有自己的特有屬性
使用情況:
    1.一個程式中併發任務比較多,比較簡單,適合使用多執行緒
    2.如果資料程式比較複雜,特別是可能多個任務通訊比較多的時候
      要考慮使用執行緒同步互斥的複雜性
    3.多個任務存在明顯差異,和功能分離的時候沒有必要一定寫入到一個程式中
    4.使用Python要考慮到GIL的問題
Pyhthon執行緒GIL問題:
    GIL (全域性直譯器鎖)
    Python —>支援執行緒操作—>出現IO同步互斥—>加鎖—>超級鎖,給直譯器加鎖
    後果:
        同一時刻一個直譯器只解釋一個執行緒 
        此時其他執行緒需要等待。大大降低了Python執行緒的執行效率
        只能實現併發不能實現並行
Python GIL問題解決方案:
    1.修改c直譯器
    2.儘量使用多程式進行並行操作
    3.Python執行緒儘量用在高延遲多阻塞的IO情形
    3.不使用CPython   使用C#、JAVA 做的得直譯器

網路伺服器基礎:
    迴圈伺服器::
        單程式程式,迴圈接受客戶請求,處理請求,處理完畢後再接受下一次請求
        特點:
            每次只能處理一個客戶端請求,如果客戶端長期佔有伺服器則無法處理其他客戶端
            請求
        優點:
            實現簡單,佔用資源少
        缺點:
            無法同時處理多個客戶端,體驗差
        使用情況:
            任務短暫,可以快速完成,udp比tcp更適合迴圈
    併發伺服器:
        能夠同時處理多個客戶端任務請求
        IO併發:
            IO多路複用 協程
            優點:
                可以實現IO併發操作,佔用系統資源少
            缺點:
                不能夠監控CPU密集的情況,並不能有長期阻塞
        多程式/執行緒併發:
            為每個客戶端單獨提供一個程式或執行緒,處理客戶端請求
            優點:
                客戶端可以長期佔有伺服器
            缺點:
                消耗計算機資源比較多


相關文章