異常處理
try:
names[3]
data["name"]
except KeyError as e:#抓取一個錯誤
print("沒有這個key", e)
except (err1, err2) as e:#抓取兩個錯誤
print("列表操作錯誤", e)
except Exception as e:#抓取所有錯誤
print("出錯了", e)
else:
print("一切正常")
finally:
print("無論對錯都執行")
斷言
assert type(obj.name) is str
print("斷言正確")
Socket網絡編程
-
Socket又稱"套接字",應用程序通常通過"套接字"向網絡發出請求或者應答網絡請求,使主機間或者一臺計算機上的進程間可以通訊。
- 一些其他協議
協議 功能用處 端口號 Python 模塊 http 網頁訪問 80 httplib, urllib, xmlrpclib smtp 發送郵件 25 smtplib dns 域名/IP地址轉換 53 ftp 文件傳輸 20 ftplib, urllib ssh 爲網絡服務提供安全性的協議 22 snmp 簡單網絡管理協議 icmp ping 互聯網控制報文協議 dhcp 動態主機配置協議 ...
- 一些其他協議
-
所有協議本質上都是由:發send和收receive
-
Socket是對以上協議發send和收receive接口的封裝
-
粘包:服務端連續發送數據是,緩存區裏兩條挨着的數據會黏在一起發送給客戶端
-
解決辦法:兩次數據發送中間加一次交互
-
OSI七層
應用 表示 會話 傳輸 TCP/IP 三次握手,四次斷開 1、syn->2、syn/ack->3、ACK UDP不安全的數據傳輸 網絡 ip 數據鏈路 mac 物理層
-
一個機器(服務器)上可以開65535個端口(port) 通信的實現要通過IP+port
Nginx 80 MySQL 3306
-
發送端流程
import socket socket.TCP/IP connect(a.ip,a.port) socket.send(hello) socket.recv() socket.close()
- 實例 ```python import socket client = socket.socket() # 聲明socket類型,同時生成socket連接對象 client.connect(("localhost", 9000)) # client.send(b"Hello World!")#python3裏要轉字節傳輸 while True: msg = input(">>:").strip() if len(msg) == 0: continue client.send(msg.encode("utf-8")) data = client.recv(1024) # 收1024字節 print("recv:", data.decode()) client.close() ```
-
接收端(服務端)
import socket socket.TCP/IP listen(ip,port) waiting()等 recv()收 send()回覆
- 實例
server = socket.socket() # 聲明socket類型,同時生成socket連接對象 server.bind(("localhost", 9000)) # 綁定到要監聽端口 server.listen(5) # 監聽 print("我要開始等電話了") while True: conn, addr = server.accept() # 等電話打進來 # conn就是客戶端連過來而在服務器端爲其生成的一個連接實例 print(conn, addr) print("電話來了") while True: data = conn.recv(1024) print("recv:", data.decode()) if not data: print("client has lost...") conn.send(data.upper())#服務端最多能發送32M server.close()
- 實例
-
Socket Families(地址簇)
socket.AF_UNIX unix本機進程間通信 socket.AF_INET ipV4 socket.AF_INET6 ipV6 Socket Types socket.SOCK_STREAM #for tcp socket.SOCK_DGRAM #for udp socket.SOCK_RAW #原始套接字,普通的套接字無法處理ICMP、IGMP的網絡報文,而SOCK_RAW可以;其次SOCK_RAW也可以處理特殊的IPv4報文;此外,利用原始套接字,可以通過IP_HDRINCL套接字選項由用戶構造IP頭(可以僞造物理攻擊即doc攻擊)。
ftp server流程
1、讀取文件
2、檢測文件是否存在
3、打開文件
4、檢測文件大小
5、發文件大小給客戶端
6、等客戶端確認
7、開始邊讀邊發數據
8、發送md5
多任務 - 線程
-
概念:簡單地說就是操作系統可以同事運行多個任務,如同時聽歌、用word工作、瀏覽器上網
-
單核CPU執行多任務:操作系統讓任務交替執行,任務1執行0.01s,任務2執行0.01s,任務,3執行0.01s...
- 並行:真的多任務
- 併發:假的多任務(時間片輪轉)
-
線程:
-
一個程序運行起來之後,一定有一個執行代碼的東西,這個東西就叫做線程
-
python的thread模塊是比較底層的模塊,python的threading模塊對thread做了一些包裝,可以更加方便的被使用
-
查看正在運行的線程用:threading.enumerate()
-
當調用Thread的時候,不會創建線程
-
當調用Thread創建出來的實例對象的start方法的時候,纔會創建線程以及讓個這個線程開始運行
-
同時創建多個子線程,子線程執行的先後順序是不固定的(隨機的)
-
如果創建Thread時執行的函數,函數運行結束就意味着這個子線程結束
-
子線程一定先於主線程結束
-
創建子線程:
- 通過指定函數創建子線程
- 創建帶參數的線程threading.Thread(target=test1, args=(參數,))
- target:指定將來這個線程去哪個函數執行代碼
- args:指定將來調用函數的時候傳遞什麼數據過去(args必須是個元組)
- 通過繼承Thread類創建子線程
- 通過指定函數創建子線程
-
多線程共享全局變量:
- 在一個函數中對全局變量進行修改的時候,是否需要用global進行說明,要看是否對全局變量的指向進行了修改
- 如果修改了指向,那麼必須用global,如果僅僅是修改了指向的空間中的數據,此時不必使用global
- 多線程共享全局變量的時候會存在資源競爭
-
同步
- 同步就是協同步調,按預定的先後順序運行,如:你說完·我再說
- 進程、線程同步,可以理解爲進程或線程A和B一塊配合,A執行到一定程度的時候要依靠B的某個結果, 於是停下來,讓B運行;B執行,將結果給A;A再繼續操作
-
互斥鎖
- 當多個線程幾乎同時修改某一個共享數據的時候,需要進行同步控制
-
死鎖
-
在線程間共享多個資源的時候,如果兩個線程分別佔有一部分資源,並且同時等待對方的資源,就會造成死鎖
-
避免死鎖
- 程序設計時要儘量避免(銀行家算法)
- 添加超時時間
-
-
進程、線程、協程對比
- 進程是資源分配單位
- 線程是操作系統調度的單位
- 進程切換需要的資源最大,效率很低
- 線程切換需要的資源一般,效率一般(當然了在不考慮GIL的情況下)
- 協程切換任務資源很小,效率高
- 多進程、多線程根據CPU核數不一樣可能是並行的,但是協程是在一個線程中所以是併發
SocketServer:實現併發處理
SocketServer.TCPServer
SocketServer.UDPServer
SocketServer.UnixStreamServer
SocketServer.UnixDatagramServer
- 1、你必須自己創建一個請求處理類,並且這個類要繼承BaseRequestHandler,並且還有重寫父親類裏的handler()
- 2、你必須實例化TCPServer,並且傳遞server ip 和你上面創建的請求處理類,給這個TCPServer
- 3、調用handle_request()和server_forever()方法
- server.handle_request()#只處理一個請求
- server.server_forever()#處理多個請求,永遠執行
- 4、調用server_close()去關閉這個socket
- 實例
import socketserver class MyTCPHandler(socketserver.BaseRequestHandler): ''' 繼承socketserver,重寫handle方法 ''' def handle(self): while True: try: # self.request是TCP socket 鏈接到客戶端 self.data = self.request.recv(1024).strip() print("{} worte:".format(self.client_address[0])) print(self.data) self.request.sendall(self.data.upper()) except ConnectionResetError as e: print("err:",e) break if __name__ == "__main__": HOST, PORT = "localhost", 9000 server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)#多線程 # server = socketserver.ForkingTCPServer((HOST, PORT), MyTCPHandler)#多進程(linex) server.serve_forever()
- 實例
練習:開發一個支持多用戶在線的FTP程序
要求:
1、用戶加密認證
2、允許同時多用戶登錄
3、每個用戶有自己的home目錄,且只能訪問自己的home目錄
4、對用戶進行磁盤配額,每個用戶的可用空間不同
5、允許用戶在ftp server上隨意切換目錄
6、允許用戶查看當前目錄下的文件
7、允許上傳和下載文件,保證文件的一致性
8、文件傳輸過程中顯示進度條
9、附加功能:支持文件斷點續傳