Python socket 套接字實現通訊詳解
首先:我們介紹一下socket什麼是socket:
1. socket 在作業系統中它是處於應用層與傳輸層的抽象層,它是一組操作起來非常簡單的介面(接收資料的),此介面接受資料之後交個作業系統
那麼為什麼?直接給作業系統不是更方便嗎?那麼你就想錯了
因為作業系統的介面遠比我們想象的要醜陋複雜,使用作業系統交換資料,非誠繁瑣,開發者們只能想辦法讓一箇中間人和他們打交道,來簡單的實現資料交換,那麼就是socket套接字.它的作用就是:與作業系統之間資料交換將這些繁瑣的操作,進行高度化封裝,和簡化,
2.我們能夠用它實現簡單的通訊
在Python中有一個簡單的內建socket 模組我們可以用它實現簡單的基於TCP協議的通訊
#基於切換連線的迴圈通訊 import socket #首先我們在檔案中匯入socket 模組 phone = socket.socket() #例項化一個物件 phone.bind(('127.0.01',8765))#bind是存放ip地址的(這裡存放的是本地的IP地址) phone.listen(5)#可以設定連線的個數,while 1:#迴圈等待連線 conn,adds = phone.accept() while 1:#要迴圈聊天我們要重複接收發送 try: #異常處理 receives_commands = conn.recv(1024) #接收命令請求,最多接收1024位元組當然你也可以調整 receivse_commands = receives_commands.decode('utf-8')#網路傳輸是以位元組的形勢的所以我們要進行解碼 print(f'來自客戶端的訊息{receives_commands}') #列印訊息 if receives_commands.upper(0 == 'Q':break #正常結束 dispatch_orders = inport('請輸入:').strip().encode('utf-8') conn.send(dispatch_orders) except ConnectionResetError:#客戶端異常結束 print('客戶端終端') break conn.close() #關閉連線 phone.close#關閉服務端 #客戶端 import socket phone = socket.socket() phone.connect(('127.0.01',8765)) #連線服務端地址 while 1: dispatch_orders = inport('請輸入:').strip().encode('utf-8')#傳送請求 if not dispatch_orders:print('不能為空')#不能為空 phone.send(dispatch_orders) #傳送 if dispatch_orders.upper() ==b'Q':#正常退出 break receives_commands = phone.recv(1024)#接收服務端的回執 receives_commands = receives_commands.decode('utf-8')#解碼 print(f'來自客戶端的訊息{receives_commands}') #列印 phone.close()#關閉客戶端
那麼我們就通過socket實現了一個簡單的通訊連結迴圈
其中我們需要注意的是:
1.阻塞 accept 和recv 當伺服器和客戶端都屬於同種類阻塞時,那麼誰都是同步接受或同步傳送的狀態那麼是處於靜止的,這樣是不合理的(就是bug)
2.當我們設計時我們需要知道傳送不能為空,不然服務端是接收不到訊息的所以我們設定一個判斷
有時我們會發現當我們接受的超過1024位元組會發生什麼?
那麼下面我們就來將回答下這個問題:
下面我們引入一個作業系統的模組
Python中 subprocess 模組就是用來和cmd 命令列進行交流的模組
obj = subprocess.Popen('dir',#例項化物件括號內第一個引數就是我們的cmd命令列的命令,這裡我們寫的是dir顯示資料夾中內容 shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,) print(obj.stdout.read().decode('gbk')) # 正確命令 print(obj.stderr.read().decode('gbk')) # 錯誤命令
那麼我們在這個基礎上建立一個服務端響應客戶端命令的機制
import socket import subprocess phone = socket.socket() phone.bind(('127.0.01',8695)) phone.listen(5) while 1: conn,adds = phone.accept() while 1: try: receives_commands = conn.recv(1024) if receiver_commands ==b'Q':break #obj = subprocess.Popen(Receiving_instructiors,# shell= True,#stdout = subprocess.PIPE,#stderr = subprocess.PIPE ) obj = subprocess.Popen(receives_commands.decode('utf-8')#動態的傳入命令 shell = True stdout = subprocess.PIPE stderr = subprocess.PIPE ) # print(obj.stdout.read().decode('gbk')) # 正確命令 # print(obj.stderr.read().decode('gbk')) # 錯誤命令 ret = obj.stodut.read()+obj.stderr.read()#將產生的內容進行拼接 conn.send(ret) except ConnectionResetError: print('客戶端終端') break conn.close() phone.close() import socket phone = socket.socket() phone.connect(('127.0.01',8695)) while 1: dispatch_orders = inport('請輸入命令:').strip().encode('utf-8') if not dispatch_orders:print('輸入不能為空') phone.send(dispatch_orders) if dispatch_orders.upper() ==b'Q':break receives_commands = phone.recv(1024) receives_commands = receives_commands.decode('utf-8') print(f'來自客戶端的訊息{receives_commands}') phone.close()
那麼我們就會發現一個問題,當我們輸入的help命令的時候超過了1024位元組那麼怎麼辦
還發現一個問題那就是當我們輸入的下個命令時,還是出來help命令的未傳輸完成的那部分那麼就是這就是粘包了
那麼是什麼造成的呢?
怎樣解決呢?
下次講解
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。