網路程式設計協議
1.osi七層模型
應用層 表示層 會話層 傳輸層 網路層 資料鏈路層 物理層
2.套接字 socket
有兩類,一種基於檔案型別,一種基於網路型別
3.Tcp和udp協議
Tcp協議:面向連線,資料可靠,傳輸效率低,面向位元組流
建立連線與斷開連線的過程(三次握手,四次揮手)
建立連線(三次握手):
1.客戶端先發出訊息到服務端,請求連線
2.服務端收到資訊後,給客戶端反饋一個資訊,等待客戶端回覆
3.客戶端收到服務端的反饋資訊後,再像服務端發出收到訊息,連線建立
斷開連線(四次揮手):
1.客戶端先發出訊息到服務端,請求斷開連線
2.服務端先傳送一個資訊,讓客戶端進行等待服務端處理通道中的資料
3.服務端處理完通道中的資料,給客戶端傳送一個資訊,表示已經處理完資料,等待客戶端回覆
4.客戶端收到訊息後,給服務端傳送一個回覆資訊,服務端收到後,斷開連線
tcp服務端
import socket server = socket.socket() server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) ip_port = ("127.0.0.1",8004) server.bind(ip_port) server.listen(3) while 1: conn,addr = server.accept() while 1: from_client_msg = conn.recv(1024) from_client_str = from_client_msg.decode("utf-8") print(from_client_str) to_client_msg = input("服務輸入") conn.send(to_client_msg.encode("utf-8"))
tcp客戶端
import socket client = socket.socket() ip_port = ("127.0.0.1",8004) client.connect(ip_port) while 1: to_server_msg = input("客戶輸入") client.send(to_server_msg.encode("utf-8")) from_server_msg = client.recv(1024) print(from_server_msg.decode("utf-8"))
Udp協議:面向無連線,資料不可靠,傳輸效率高,面向報文
upd服務端
import socket udp_server = socket.socket(type=socket.SOCK_DGRAM) ip_port = ("127.0.0.1",8007) udp_server.bind(ip_port) from_client_msg,client_addr = udp_server.recvfrom(1024) udp_server.sendto(b"gun",client_addr) print(from_client_msg,client_addr)
upd客戶端
import socket udp_client = socket.socket(type=socket.SOCK_DGRAM) ip_port = ("127.0.0.1",8007) udp_client.sendto(b"hello",ip_port) from_server_msg,server_addr = udp_client.recvfrom(1024) print(from_server_msg,server_addr)
現在多用Tcp協議,這個更安全,但是Tcp長連線有一些問題, 會出現粘包現象, 這種現象是由緩衝區引起的
緩衝區: 將程式和網路解耦
輸入緩衝區
輸出緩衝區
Import Subprocess
sub_obj = subprocess.Popen(
‘dir’,
shell=True,
stdout=subprocess.PIPE, #正確結果的存放位置
stderr=subprocess.PIPE #錯誤結果的存放位置
)
4.粘包
兩種粘包現象:
1 連續的小包可能會被優化演算法給組合到一起進行傳送
2 第一次如果傳送的資料大小2000B,接收端一次性接受大小為1024B,這就導致剩下的內容會被下一次recv接收到,導致結果錯亂
解決粘包的方法:
方案一:由於雙方不知道對方傳送資料的長度,導致接收的時候,可能接收不全,或者多接收另外一次傳送的資訊內容,所以在傳送真實資料之前,要先傳送資料的長度,接收端根據長度來接收後面的真實資料,但是雙方有一個互動確認的過程
方案二:
使用Struct模組,在傳送前,把檔案的大小打包,做成報頭,把報頭放在檔案真實內容之前;在接收時,對傳送過來的檔案進行解包,然後列印檔案真實內容.
打包:struct.pack(‘i’,長度)
解包:struct.unpack(‘i’,位元組)
socketserver模組實現併發
我們之前寫的tcp協議的socket是不是一次只能和一個客戶端通訊,如果用socketserver可以實現和多個客戶端通訊。它是在socket的基礎上進行了一層封裝,也就是說底層
還是呼叫的socket。後面我們要寫的FTP作業,需要用它來實現併發,也就是同時可以和多個客戶端進行通訊,多個人可以同時進行上傳下載等。
服務端程式碼
import socketserver class Myserver(socketserver.BaseRequestHandler): def handle(self): while 1: from_client_msg = self.request.recv(1024) print(from_client_msg.decode("utf-8")) msg = input("服務") self.request.send(msg.encode("utf-8")) if __name__ == `__main__`: ip_port = ("127.0.0.1",8001) server = socketserver.ThreadingTCPServer(ip_port,Myserver) server.serve_forever()
客戶端程式碼
import socket client = socket.socket() client.connect(("127.0.0.1",8001)) while 1: client_msg = input("客戶:") client.send(client_msg.encode("utf-8")) from_server_msg = client.recv(1024) print(from_server_msg.decode("utf-8"))