服務端shell
import socket phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 買電話 # socket.SOCK_STREAM 流式協議 就是TCP協議 phone.bind(('127.0.0.1', 8080)) # 買電話卡 phone.listen(5) # 開機。 # 5 不是連接數,連接能夠產生N個,同一時刻只能監聽5個請求。 conn, addr = phone.accept() # 等待接電話 # 阻塞狀態 # print(222) print(conn, addr) # conn 表明的是socket通訊的對象,一個管道 client_data = conn.recv(1024) # 交流過程 print(client_data) conn.send(client_data.upper()) conn.close() phone.close()
客戶端json
import socket phone = socket.socket() # 買電話 phone.connect(('127.0.0.1', 8080)) # 撥號 msg = input('>>>').strip() phone.send(msg.encode('utf-8')) server_data = phone.recv(1024) # 限制的是最大接收字節數。 print(server_data) phone.close()
服務端與客戶端循環 聊緩存
import socket import subprocess # socket.SOCK_STREAM 流式協議 就是TCP協議 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 買電話 phone.bind(('127.0.0.1', 8080)) # 綁定電話卡,寫本身的IP (倆括號) phone.listen(5) #開機 5不是限制鏈接數,而是同一時刻只接受5個請求,能夠不寫,不寫爲默認,默承認以開啓N個 #運行後停在這裏,下邊不執行 while 1: conn,addr = phone.accept() #等待接電話 phone.accept() conn和addr分別接收phone..accept()生成的兩個參數 print(addr) #打印鏈接進來的客戶端 while 1: try: client_data = conn.recv(1024) #接受的字節數 c = client_data.decode('gbk') obj = subprocess.Popen(c, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) RET = obj.stdout.read() RET1 = obj.stderr.read() print(RET.decode('gbk')) conn.send(RET+RET1) #返回的信息 except Exception: break conn.close() phone.close()
客戶端服務器
import socket phone = socket.socket() phone.connect(('127.0.0.1', 8080)) # 撥號,寫服務端的IP (倆括號) while 1: fasong = input('>>>') if fasong.upper() == 'Q': break elif not fasong :continue #若是發送爲空,則跳過本次循環 not False3 = True phone.send(fasong.encode('gbk')) #剛給服務端發信息 server_data = phone.recv(1024) #接收服務端的信息,1024限制的是最大接受的字節數 print(server_data.decode('gbk')) phone.close()
subprocess模塊用於接收shell界面執行的命令並返回結果socket
import subprocess obj = subprocess.Popen('ip a', #輸入命令 shell=True, #shell爲Tree stdout=subprocess.PIPE, #stdout接收正確 stderr=subprocess.PIPE) #stderr接收錯誤返回 RET = obj.stdout.read() print(RET.decode('utf-8'))
1. 流式協議.數據所有都像水同樣連在一塊兒,一次性發送多字節(所有在客戶端操做系統的緩存區),客戶端每次只取1024字節,剩餘字節在緩存區等待下次取tcp
client_data = conn.recv(1024)
server_data = phone.recv(1024)
2.針對於(客戶端/服務端)發送的連續的小的數據,對方會一次性接收.spa
客戶端操作系統
import socket phone = socket.socket() phone.connect(('127.0.0.1', 8080)) # 撥號,寫服務端的IP (倆括號) phone.send(b'hello') #先發送hello phone.send(b'word') #緊接着在發送word while 1: server_data = phone.recv(1024) #接收服務端的信息,1024限制的是最大接受的字節數 print(server_data.decode('gbk')) phone.close()
服務端code
import socket import subprocess # socket.SOCK_STREAM 流式協議 就是TCP協議 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 買電話 phone.bind(('127.0.0.1', 8080)) # 綁定電話卡,寫本身的IP (倆括號) phone.listen(5) #開機 5不是限制鏈接數,而是同一時刻只接受5個請求,能夠不寫,不寫爲默認,默承認以開啓N個 #運行後停在這裏,下邊不執行 conn,addr = phone.accept() #等待接電話 phone.accept() conn和addr分別接收phone..accept()生成的兩個參數 print(addr) #打印鏈接進來的客戶端 while 1 : client_data = conn.recv(1024) #接受的字節數 print(client_data) conn.send(client_data.upper()) #返回的信息 conn.close() phone.close() ('127.0.0.1', 53961) #服務端接收客戶端的信息連在了一塊兒 b'helloword'
客戶端server
import socket import time phone = socket.socket() phone.connect(('127.0.0.1', 8080)) # 撥號,寫服務端的IP (倆括號) phone.send(b'hello') time.sleep(0.1) #等待0.1秒在發送word phone.send(b'word') while 1: server_data = phone.recv(1024) #接收服務端的信息,1024限制的是最大接受的字節數 print(server_data.decode('gbk')) phone.close()
服務端
import socket import subprocess # socket.SOCK_STREAM 流式協議 就是TCP協議 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 買電話 phone.bind(('127.0.0.1', 8080)) # 綁定電話卡,寫本身的IP (倆括號) phone.listen(5) #開機 5不是限制鏈接數,而是同一時刻只接受5個請求,能夠不寫,不寫爲默認,默承認以開啓N個 #運行後停在這裏,下邊不執行 conn,addr = phone.accept() #等待接電話 phone.accept() conn和addr分別接收phone..accept()生成的兩個參數 print(addr) #打印鏈接進來的客戶端 while 1 : client_data = conn.recv(1024) #接受的字節數 print(client_data) conn.send(client_data.upper()) #返回的信息 conn.close() phone.close() ('127.0.0.1', 53985) #接受的字符分開了 b'hello' b'word'
發送固定頭部,固定頭部包含(數據的總大小) + 數據
struct模塊 將一個數據,int 轉化爲固定的bytes
import struct ret = struct.pack('i',151923212) #將151923212 轉換爲固定的bytes類型 print(ret,type(ret) ,len(ret),sep='\n') #sep='\n',將分隔符換爲\n ret1 = struct.unpack('i',ret) print(ret1) b'\x0c*\x0e\t' <class 'bytes'> 4 #轉爲固定的4字節 (151923212,)
一旦數據傳入過大則struct模塊報錯, struct模塊不能轉譯 較長的字符串
服務端:
將數據大小經過struct模塊轉爲固定大小發給客戶端
import socket import subprocess import struct # socket.SOCK_STREAM 流式協議 就是TCP協議 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 買電話 phone.bind(('127.0.0.1', 8080)) # 綁定電話卡,寫本身的IP (倆括號) phone.listen(5) #開機 5不是限制鏈接數,而是同一時刻只接受5個請求,能夠不寫,不寫爲默認,默承認以開啓N個 #運行後停在這裏,下邊不執行 conn,addr = phone.accept() #等待接電話 phone.accept() conn和addr分別接收phone..accept()生成的兩個參數 print(addr) #打印鏈接進來的客戶端 while 1 : #如下爲粘包解決方法 try: client_data = conn.recv(1024) # 接受的字節數 obj = subprocess.Popen(client_data.decode('utf-8'), #將接收的字節在本地shell執行 並返回結果 shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,) ret = obj.stdout.read() #正確結果 ret1 = obj.stderr.read() #錯誤結果 ss = len(ret1 + ret) #算返回結果的總長度 ret2 = struct.pack('i',ss) #經過struct將算返回結果的總長度變爲固定長度的bytes類型 conn.send(ret2) #發送報頭 conn.send(ret) #發送正確結果 conn.send(ret1) #發送錯誤結果 except Exception: break conn.close() phone.close()
客戶端:
客戶端根據服務端發來的內容大小取內容
import socket import time import struct phone = socket.socket() phone.connect(('127.0.0.1', 8080)) # 撥號,寫服務端的IP (倆括號) while 1: msg = input('>>>').strip() #輸入發往服務端的內容,若是是q退出,若是是空重新輸入 if msg.upper() == 'Q': break elif not msg: #not + 空就是 True 執行continue 從新輸入 continue phone.send(msg.encode('utf-8')) #往服務端發送內容 head = phone.recv(4) #接收報頭 報頭大小爲固定4字節 head_size = struct.unpack('i', head)[0] #直接將報頭反解爲服務端發送內容的長度,返回是元組,取第一個值 datas = 0 #定義一個datas大小爲0 res = b'' #定義一個空的bytes類型的變量 while datas < head_size: #若是datas小於發送的內容的總長度爲真 data = phone.recv(1024) #取1024字節 res = res + data #將取出的內容追加到res裏 datas += len(data) #datas加上取出內容字節的大小 print(res.decode('gbk')) #讀出res裏的內容 phone.close()
服務端:
將服務端發送數據大小寫到字典,
將字典轉爲json,
再將json轉爲字符串,
取字符串長度給struct模塊轉爲固定大小
將固定大小,bytes類型的字典以及全部數據傳給客戶端
import socket import subprocess import struct import json # socket.SOCK_STREAM 流式協議 就是TCP協議 phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 買電話 phone.bind(('127.0.0.1', 8080)) # 綁定電話卡,寫本身的IP (倆括號) phone.listen(5) #開機 5不是限制鏈接數,而是同一時刻只接受5個請求,能夠不寫,不寫爲默認,默承認以開啓N個 #運行後停在這裏,下邊不執行 conn,addr = phone.accept() #等待接電話 phone.accept() conn和addr分別接收phone..accept()生成的兩個參數 print(addr) #打印鏈接進來的客戶端 while 1 : try: client_data = conn.recv(1024) # 接受的字節數 obj = subprocess.Popen(client_data.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,) ret = obj.stdout.read() ret1 = obj.stderr.read() ss = len(ret1 + ret) head_dict = { #定義一個字典,total_size的值爲發送數據的大小,字典裏可定義多個鍵值傳遞多種信息 'total_size':ss } head_json = json.dumps(head_dict) #將字典轉爲json格式 head_bytes = head_json.encode('utf-8') #再將json格式轉爲bytes格式 ret2 = struct.pack('i',len(head_bytes)) #將轉爲bytes格式的長度經過struct轉爲固定字節 conn.send(ret2) #發送固定字節 conn.send(head_bytes) #發送bytes類型的字典 conn.send(ret) #發送內容 conn.send(ret1) except Exception: break conn.close() phone.close()
客戶端:
將服務端發送的頭部大小獲取字典大小
經過字典大小獲取內容大小
經過內容大小獲取內容
import socket import json import struct phone = socket.socket() phone.connect(('127.0.0.1', 8080)) # 撥號,寫服務端的IP (倆括號) while 1: msg = input('>>>').strip() if msg.upper() == 'Q': break elif not msg: continue phone.send(msg.encode('utf-8')) he = struct.unpack('i', phone.recv(4))[0] #將頭部的大小(phone.recv(4))經過struct模塊解析出字典bytes類型的大小 head_dic_bytes = phone.recv(he) #經過解析出字典bytes類型的大小獲取bytes類型字典的數據 head_json = head_dic_bytes.decode('utf-8') #將bytes數據反解爲json類型 head_doc = json.loads(head_json) #反解json得到字典 datas = 0 res = b'' while datas < head_doc['total_size']: #將字典total_size鍵對應的內容大小的值取出,得到內容 data = phone.recv(1024) res = res + data datas += len(data) print(res.decode('gbk')) phone.close()
服務端
import socket udp_sk = socket.socket(type=socket.SOCK_DGRAM) # (type=socket.SOCK_DGRAM)基於UDP的套接字TCP爲socket.AF_INET, socket.SOCK_STREAM udp_sk.bind(('127.0.0.1', 10000)) #綁定服務器套接字 while 1: msg, addr = udp_sk.recvfrom(1024) #tcp裏的accept()裏的recv() 是阻塞的 這裏的recvfrom(1024)是非阻塞的 print(msg.decode('utf-8')) #打印內容 udp_sk.sendto(b'hi',addr) #返回給客戶端的內容
客戶端
import socket ip = ('127.0.0.1',10000) #建立個IP udp_sk=socket.socket(type=socket.SOCK_DGRAM) #開啓udp的socket while 1: sd = input('>>>').encode('utf-8') udp_sk.sendto(sd,ip) #給服務端發送內容 back_msg,addr=udp_sk.recvfrom(1024) #獲取服務端回覆的內容 print(back_msg.decode('utf-8'),addr) #打印服務端回覆的內容 udp_sk.close()