1.先說下subprocess模塊的用法,爲了舉個黏包的例子shell
# 經過一個例子 來認識網絡編程中的一個重要的概念 # 全部的客戶端執行server端下發的指令,執行完畢後,客戶端將執行結果給返回給服務端 import subprocess # 這個模塊其實並很差用,這裏爲了舉例子。調用操做系統的命令模塊 res = subprocess.Popen('dir', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # 執行dir命令,並將標準輸出和錯誤內容裝到了管道中 print('stdout : ', res.stdout.read().decode('gbk')) # 從管道中獲取控制檯的內容,windows控制檯執行完畢後,獲得的是bytes類型的,須要解碼成gbk纔可不亂碼顯示,windows控制檯返回的是gbk的,因此這裏要gbk解碼 print('stderror: ', res.stderr.read().decode('gbk'))
2.寫一個tcp的server端和client,模擬黏包的現象,tcp端發送windows的命令給client,client接收後執行該命令後,將控制檯返回的內容傳輸到server端編程
tcpserver.pywindows
# 經過一個例子 來認識網絡編程中的一個重要的概念 # 全部的客戶端執行server端下發的指令,執行完畢後,客戶端將執行結果給返回給服務端 # 基於tcp實現遠程執行命令 # 在server下發windows操做系統命令給client,client執行完畢後返回給sercer # 出現了黏包現象 # 數據亂了,數據沒有接收完,下次接收接收到了未接收到的數據等現象 # tcp不會丟包,會黏包。 # 當傳輸的包很大的時候,tcp協議會將其拆分開進行傳輸。 import socket sk = socket.socket() sk.bind(('127.0.0.1', 8080)) sk.listen() conn, addr = sk.accept() while True: cmd = input('輸入想要客戶端windows系統想要執行的命令:') conn.send(cmd.encode('utf-8')) msg = conn.recv(1024).decode('utf-8') print(msg) conn.close() sk.close()
tcpclient.py緩存
# client接收服務端命令 import socket import subprocess sk = socket.socket() sk.connect(('127.0.0.1', 8080)) while True: cmd = sk.recv(1024).decode('utf-8') res = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout = 'stdout : ' + res.stdout.read().decode('gbk') stderr = 'stderr : ' + res.stderr.read().decode('gbk') #print(stdout) #print(stderr) # res.stdout.read() 爲cmd命令執行後返回的結果,返回的是bytes類型數據 sk.send(stdout.encode('utf-8')) sk.send(stderr.encode('utf-8')) sk.close()
3.udp不黏包,但會丟包例子,與上相似網絡
udpserver.pysocket
# 測試結果,udp不會黏包,但udp會丟包,數據發送出去後,一旦另外一端接收的緩存不夠大,而發送的數據很大時,未接收的數據,會丟棄掉。同時udp大了緩存限制會丟棄包 import socket sk = socket.socket(type=socket.SOCK_DGRAM) #sk.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) # 避免服務重啓的時候報address already in use。加上這個解決 sk.bind(('127.0.0.1', 8081)) msg, addr = sk.recvfrom(1024) while True: cmd = input('輸入想要客戶端windows系統想要執行的命令:') if cmd == 'q': break sk.sendto(cmd.encode('utf-8'), addr) msg, addr = sk.recvfrom(1024) print(msg.decode('utf-8')) sk.close()
udpclient.pytcp
# client接收服務端命令 import socket import subprocess sk = socket.socket(type=socket.SOCK_DGRAM) ip_port = ('127.0.0.1', 8081) sk.sendto(b'hello', ip_port) while True: cmd, addr= sk.recvfrom(1024) res = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout = 'stdout : ' + res.stdout.read().decode('gbk') stderr = 'stderr : ' + res.stderr.read().decode('gbk') #print(stdout) #print(stderr) # res.stdout.read() 爲cmd命令執行後返回的結果,返回的是bytes類型數據 sk.sendto(stdout.encode('utf-8'), ip_port) sk.sendto(stderr.encode('utf-8'), ip_port) sk.close()
4.tcp爲何會黏包測試
黏包是這樣出現的spa
tcp的拆包機制是相似這樣的操作系統
5.udp爲何不會黏包