Python socket 套接字實(shí)現(xiàn)通信詳解
首先:我們介紹一下socket什么是socket:
1. socket 在操作系統(tǒng)中它是處于應(yīng)用層與傳輸層的抽象層,它是一組操作起來(lái)非常簡(jiǎn)單的接口(接收數(shù)據(jù)的),此接口接受數(shù)據(jù)之后交個(gè)操作系統(tǒng)
那么為什么?直接給操作系統(tǒng)不是更方便嗎?那么你就想錯(cuò)了
因?yàn)椴僮飨到y(tǒng)的接口遠(yuǎn)比我們想象的要丑陋復(fù)雜,使用操作系統(tǒng)交換數(shù)據(jù),非誠(chéng)繁瑣,,開(kāi)發(fā)者們只能想辦法讓一個(gè)中間人和他們打交道,來(lái)簡(jiǎn)單的實(shí)現(xiàn)數(shù)據(jù)交換,那么就是socket套接字.它的作用就是:與操作系統(tǒng)之間數(shù)據(jù)交換將這些繁瑣的操作,進(jìn)行高度化封裝,和簡(jiǎn)化,
2.我們能夠用它實(shí)現(xiàn)簡(jiǎn)單的通信
在Python中有一個(gè)簡(jiǎn)單的內(nèi)置socket 模塊我們可以用它實(shí)現(xiàn)簡(jiǎn)單的基于TCP協(xié)議的通信
#基于切換連接的循環(huán)通信 import socket #首先我們?cè)谖募袑?dǎo)入socket 模塊 phone = socket.socket() #實(shí)例化一個(gè)對(duì)象 phone.bind(('127.0.01',8765))#bind是存放ip地址的(這里存放的是本地的IP地址) phone.listen(5)#可以設(shè)置連接的個(gè)數(shù), while 1:#循環(huán)等待連接 conn,adds = phone.accept() while 1:#要循環(huán)聊天我們要重復(fù)接收發(fā)送 try: #異常處理 receives_commands = conn.recv(1024) #接收命令請(qǐng)求,最多接收1024字節(jié)當(dāng)然你也可以調(diào)整 receivse_commands = receives_commands.decode('utf-8')#網(wǎng)絡(luò)傳輸是以字節(jié)的形勢(shì)的所以我們要進(jìn)行解碼 print(f'來(lái)自客戶(hù)端的消息{receives_commands}') #打印消息 if receives_commands.upper(0 == 'Q':break #正常結(jié)束 dispatch_orders = inport('請(qǐng)輸入:').strip().encode('utf-8') conn.send(dispatch_orders) except ConnectionResetError:#客戶(hù)端異常結(jié)束 print('客戶(hù)端終端') break conn.close() #關(guān)閉連接 phone.close#關(guān)閉服務(wù)端 #客戶(hù)端 import socket phone = socket.socket() phone.connect(('127.0.01',8765)) #連接服務(wù)端地址 while 1: dispatch_orders = inport('請(qǐng)輸入:').strip().encode('utf-8')#發(fā)送請(qǐng)求 if not dispatch_orders:print('不能為空')#不能為空 phone.send(dispatch_orders) #發(fā)送 if dispatch_orders.upper() ==b'Q':#正常退出 break receives_commands = phone.recv(1024)#接收服務(wù)端的回執(zhí) receives_commands = receives_commands.decode('utf-8')#解碼 print(f'來(lái)自客戶(hù)端的消息{receives_commands}') #打印 phone.close()#關(guān)閉客戶(hù)端
那么我們就通過(guò)socket實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的通信鏈接循環(huán)
其中我們需要注意的是:
1.阻塞 accept 和recv 當(dāng)服務(wù)器和客戶(hù)端都屬于同種類(lèi)阻塞時(shí),那么誰(shuí)都是同步接受或同步發(fā)送的狀態(tài)那么是處于靜止的,這樣是不合理的(就是bug)
2.當(dāng)我們?cè)O(shè)計(jì)時(shí)我們需要知道發(fā)送不能為空,不然服務(wù)端是接收不到消息的所以我們?cè)O(shè)置一個(gè)判斷
有時(shí)我們會(huì)發(fā)現(xiàn)當(dāng)我們接受的超過(guò)1024字節(jié)會(huì)發(fā)生什么?
那么下面我們就來(lái)將回答下這個(gè)問(wèn)題:
下面我們引入一個(gè)操作系統(tǒng)的模塊
Python中 subprocess 模塊就是用來(lái)和cmd 命令行進(jìn)行交流的模塊
obj = subprocess.Popen('dir',#實(shí)例化對(duì)象括號(hào)內(nèi)第一個(gè)參數(shù)就是我們的cmd命令行的命令,這里我們寫(xiě)的是dir顯示文件夾中內(nèi)容 shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) print(obj.stdout.read().decode('gbk')) # 正確命令 print(obj.stderr.read().decode('gbk')) # 錯(cuò)誤命令
那么我們?cè)谶@個(gè)基礎(chǔ)上建立一個(gè)服務(wù)端響應(yīng)客戶(hù)端命令的機(jī)制
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')#動(dòng)態(tài)的傳入命令 shell = True stdout = subprocess.PIPE stderr = subprocess.PIPE ) # print(obj.stdout.read().decode('gbk')) # 正確命令 # print(obj.stderr.read().decode('gbk')) # 錯(cuò)誤命令 ret = obj.stodut.read()+obj.stderr.read()#將產(chǎn)生的內(nèi)容進(jìn)行拼接 conn.send(ret) except ConnectionResetError: print('客戶(hù)端終端') break conn.close() phone.close() import socket phone = socket.socket() phone.connect(('127.0.01',8695)) while 1: dispatch_orders = inport('請(qǐng)輸入命令:').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'來(lái)自客戶(hù)端的消息{receives_commands}') phone.close()
那么我們就會(huì)發(fā)現(xiàn)一個(gè)問(wèn)題,當(dāng)我們輸入的help命令的時(shí)候超過(guò)了1024字節(jié)那么怎么辦
還發(fā)現(xiàn)一個(gè)問(wèn)題那就是當(dāng)我們輸入的下個(gè)命令時(shí),還是出來(lái)help命令的未傳輸完成的那部分那么就是這就是粘包了
那么是什么造成的呢?
怎樣解決呢?
下次講解
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Python隨機(jī)生成數(shù)模塊random使用實(shí)例
這篇文章主要介紹了Python隨機(jī)生成數(shù)模塊random使用實(shí)例,本文直接給出示例代碼,需要的朋友可以參考下2015-04-04tensorflow 獲取模型所有參數(shù)總和數(shù)量的方法
今天小編就為大家分享一篇tensorflow 獲取模型所有參數(shù)總和數(shù)量的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-06-06Django 登錄注冊(cè)的實(shí)現(xiàn)示例
本文主要介紹了Django 登錄注冊(cè)的實(shí)現(xiàn)示例,這是做網(wǎng)頁(yè)登錄和注冊(cè)基本上都是必要一步,具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10詳解DeBug Python神級(jí)工具PySnooper
這篇文章主要介紹了詳解DeBug Python神級(jí)工具PySnooper,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07Python文件讀寫(xiě)及常用文件的打開(kāi)方式
這篇文章主要介紹了Python文件讀寫(xiě)及常用文件的打開(kāi)方式,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-09-09利用python實(shí)現(xiàn)數(shù)據(jù)分析
為什么要利用python進(jìn)行數(shù)據(jù)分析?python擁有一個(gè)巨大的活躍的科學(xué)計(jì)算社區(qū),擁有不斷改良的庫(kù),能夠輕松的集成C,C++,Fortran代碼(Cython項(xiàng)目),可以同時(shí)用于研究和原型的構(gòu)建以及生產(chǎn)系統(tǒng)的構(gòu)建。2017-01-01Django集成celery發(fā)送異步郵件實(shí)例
今天小編就為大家分享一篇Django集成celery發(fā)送異步郵件實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-12-12