1. 程式人生 > 程式設計 >Python socket 套接字實現通訊詳解

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命令的未傳輸完成的那部分那麼就是這就是粘包了

那麼是什麼造成的呢?

怎樣解決呢?

下次講解

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。