socket是一個模塊,又稱套接字,用來封裝互聯網協議(應用層如下的層)python
實現應用層如下的層的工做,提升開發效率shell
先導入socket模塊,先啓動服務端套接字,再啓動客戶端套接字json
# 服務端 import socket # 買手機 server = socket.socket() # 綁定手機號(IP,port) # IP單機模式是127.0.0.1,局域網內使用cmd中ipconfig查詢IPV4 # port設置8000之後的數據 server.bind(('127.0.0.1', 9876)) # 設置半鏈接池 server.listen(4) # 可接收多個客戶端數據鏈接,實現循環通訊 while True: # 接收客戶端鏈接 conn, addr = server.accept() # 查看對方地址 print(addr) while True: # 捕獲異常機制 try: # 接收客戶端發來的數據,可一次接收1024bytes的數據 data = conn.recv(1024) if len(date) == 0: break if data.decode('utf-8') == 'q': break print(data.decode('utf-8')) # 向客戶端發送消息 send_data = input('請輸入向客戶端發送的數據:') conn.send(send_data.encode('utf-8')) # 捕獲異常,並打印出錯誤信息 except Exception as e: print(e) break # 掛電話 conn.close()
# 客戶端 import socket # 買手機 client = socket.socket() # 創建鏈接(IP,port) client.connect(('127.0.0.1',9876)) while True: try: # 向對方發送數據 data = input('請輸入向服務端發送的數據') client.send((data.encode('utf--8'))) # 接收對方發來的數據可設置一次接收的bytes數,並打印 res_data = client.recv(1024) if len(res_data) == 0: break if res_data.decode('utf-8') == 'q': break print(res_data.decode('utf-8')) # 捕獲異常,並打印出異常 except Exception as e: print(e) break client.close()
沒法確認對方發送過來數據大小併發
在發送數據間隔短而且數據量小的狀況下,會將全部數據一次性發送socket
解決:須要確認對方發送的數據大小code
# 客戶端 # 問題1 import socket client = socket.socket() client.connect(('127.0.0.1', 9876)) while True: try: cmd = input('請輸入向服務端發送的命令:') client.send(cmd.encode('utf-8')) # 接收服務端返回的數據 # 因爲不知道會返回多少個bytes因此有問題1 date = client.recv(11910) print(len(date)) print(date.decode('gbk')) except Exception as e: print(e) break client.close()
# 客戶端 # 問題2 # 時間間隔短,並數據量小的狀況下,會將全部的數據一次性發送,接收時不知道具體有幾個 import socket client = socket.socket() client.connect(('127.0.0.1', 9876)) client.send(b'hello') client.send(b'hello') client.send(b'hello') client.send(b'hello') client.send(b'hello')
# 服務端 import socket import subprocess server = socket.socket() server.bind(('127.0.0.1', 9876)) server.listen(4) while True: conn, addr = server.accept() print(addr) while True: try: # 接收客戶端的數據,具體值不知道多大,全部有可能不能徹底接收,有可能浪費資源 cmd = conn.recv(12) if len(cmd) == 0: break cmd = cmd.decode('utf-8') if cmd == 'q': break # 調用subprocess鏈接終端,對終端進行操做,並獲取正確和錯誤的結果 obj = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # 拿到結果,並打印 result = obj.stdout.read() + obj.stderr.read() print(result.decode('gbk')) # 將結果返回給客戶端 conn.send(result) except Exception as e: print(e) break conn.close()
使用struct模塊server
struct 是一個python內置的模塊,它能夠將固定長度的數據,打包成固定格式的長度ip
模式:i:4,或其餘模式utf-8
做用:將真實數據作成一個固定長度的報頭,發送給服務端,服務端接收報頭,而後進行解包,獲取真實數據的長度,進行接收數據便可資源
import struct data = input('請輸入傳的數據').strip() data = data.encode('utf-8') # 製做報頭,須要 i 的字符串和傳入數據的長度 header = struct.pack('i',len(data)) print(header) print(len(header)) # 解包( i 的字符串和報頭)獲取真實長度,獲得一個元組,拿到元組第一個數就是真實長度 res = struct.unpack('i', header)[0] print(res) # utf-8中一箇中文是3個bytes,一個英文是1個bytes
客戶端:
1.先製做報頭,併發送
2.發送真實數據
服務端:
1.接收報頭,而且解包獲取真實數據長度
2.根據真實數據長度,接收真實數據
# 客戶端 import socket import struct client = socket.socket() client.connect(('127.0.0.1', 9876)) while True: try: cmd = input('請輸入向服務端發送的命令') cmd_bytes = cmd.encode('utf-8') # 作一個報頭 header = struct.pack('i', len(cmd_bytes)) # 發送報頭 client.send(header) # 發送真實數據 client.send(cmd_bytes) # 接受服務端返回的報頭 reheader = client.recv(4) # 解包 data_len = struct.unpack('i', reheader)[0] result = client.recv(data_len) print(result.decode('gbk')) except Exception as e: print(e) break client.close()
# 服務端 import socket import subprocess import struct server = socket.socket() server.bind(('127.0.0.1', 9876)) server.listen(5) while True: conn, addr = server.accept() while True: try: # 獲取報頭 header = conn.recv(4) # 獲取真實數據長度 data_len = struct.unpack('i', header)[0] # 準備接受真實數據 cmd = conn.recv(data_len) cmd = cmd.decode('utf-8') if cmd == 'q': break if len(cmd) == 0: break obj = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) result = obj.stdout.read() + obj.stderr.read() print(len(result)) print(result.decode('gbk')) # 將結果返回給客戶端 header = struct.pack('i', len(result)) conn.send(header) conn.send(result) except Exception as e: print(e) break conn.close()
# 客戶端 import socket import struct import json client = socket.socket() client.connect(('127.0.0.1', 9876)) while True: # 假裝電影數據 movie_name = input('請輸入電影名稱:') movie_len = 10000101 send_dic = { 'movie_name': movie_name, 'movie_len': movie_len } # 序列化 json_data = json.dumps(send_dic) # 製做報頭 json_bytes = json_data.encode('utf-8') header = struct.pack('i', len(json_bytes)) # 發送報頭 client.send(header) # 發送真實數據 client.send(json_bytes)
# 服務端 import socket import json import struct server = socket.socket() server.bind(('127.0.0.1', 9876)) server.listen(5) while True: conn, addr = server.accept() print(addr) while True: try: # 接收報頭 header = conn.recv(4) # 解包獲取真實長度 json_len = struct.unpack('i', header)[0] # 接收真實長度 json_bytes_data = conn.recv(json_len) json_data = json_bytes_data.decode('utf-8') # 反序列化獲得數據 back_dic = json.loads(json_data) print(back_dic) except Exception as e: print(e) break conn.close()