【python自动化第八篇:网络编程】
一、拾遺
動態導入模塊
目的是為了在導入模塊的過程中將模塊以字符的格式導入。?
#!/usr/bin/env python # -*- coding:utf-8 -*- #Author:wanghui lib = __import__("lib.aa") #傳統方法 lib.aa import importlib aa = importlib.import_module("lib.aa") #官方做法 print(aa.C().name)?斷言
類似于if,實際的意思就是如多對應的條件為真就執行,不為真就報錯。
assert type(1223) is str print("this is str") #等同于 if type(1223) is str:exit("must be int") print("this is str")二、socket繼續
1、淺談server端的原理:
(1)、申明socket實例 ? ? server = socket.socket(AF.INET(地址簇),sock.SOCK_STREAM(代表tcp/ip))
地址簇分類:socket.AF_INET ----> ipv4 ? ?, ? ? ? ? ? ? ? ? ? ? ? socket.AF_INET6 -------> ipv6 ? ? ?, ? ? ? ?socket.AF_UNIX --------> ?本地通信
協議類型:socket.SOCK_STREAM -----> tcp/ip ? ? , ? ? ? ? ? ??socket.SOCK_DGRAM -----> ?udp
? (2)、綁定ip地址和端口 ? ? ?server.bind(("localhost",port))
?(3)、開始監聽:while True:
conn,addr = server.accept() ? ?阻塞狀態
?(4)、循環接受信息
while True:
print("new conn",addr) ? #打印連接的客戶端ip
data = conn.recv(1024) ? ? ? ? ? ? #接受數據大小(官方最大建議8192),這邊接收數據的時候默認也是阻塞的
if not data: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?***如果客戶端 已斷開的話conn.recv就會接收到空數據
break ? ? ? ? ? ??
conn.send(data.upper()) ? ? ? ? ? ?#發送數據
? ? ? 淺談客戶端的原理:
(1)、實例化一個socket ? ? client = socket.socket()
(2)、定義一個 鏈接的地址和端口 ? ? ?client.connect(("server_ip",port))
(3)、這會兒就可以發數據了 ? ?client.send(data)
(4)、接收數據 ? client.recv()
2、通過socket實現一個簡單的ssh協議:
client端:
#!/usr/bin/env python # -*- coding:utf-8 -*- #Author:wanghui import socket,os client = socket.socket() #實例化socket client.connect(("localhost",9999)) #開始連接啦while True: #發送數據啦cmd = input("請輸入命令>>:").strip()if len(cmd) == 0:continue #如果長度為0,就繼續返回循環client.send(cmd.encode('utf-8')) #發送命令(byte)cmd_res = client.recv(1024) #接收返回結果print(cmd_res.decode()) #打印結果 client.close() #關閉連接server端:?
#!/usr/bin/env python # -*- coding:utf-8 -*- #Author:wanghui import socket,osserver = socket.socket() #申明實例 server.bind(('localhost',9999)) #綁定ip和端口 server.listen() #等待連接while True:conn,addr= server.accept() #監聽print("開始連接啦",addr)while True: #正式接受數據啦print("開始新連接啦")data = conn.recv(1024) #定義傳輸大小if not data: #如果客戶端斷開,那么就退出此次接收,重新回到監聽狀態breakprint("開始 執行客戶端命令",data)cmd_res = os.popen(data.decode()).read() #讀取客戶端命令(bytes轉換成str)print("接受之前:",len(cmd_res))if len(cmd_res) == 0:cmd_res = "cmd has no output ..."conn.send(cmd_res.encode('utf-8')) #向端發送數據,必須是bytesprint("發送完成!") server.close() #斷開連接上面的基本連接模式會出現客戶端發送的指令客戶端不能一次性全部返回的問題,這樣的話解決方式只能有:超時和確認緩沖區多少次發完的問題
然而多少次將緩沖區的內容發完呢?不曉得。。。所以只能通過在超時問題上做文章了
client:
#!/usr/bin/env python # -*- coding:utf-8 -*- #Author:wanghui import socket,os client = socket.socket() #實例化socket client.connect(("localhost",9999)) #開始連接啦while True: #發送數據啦cmd = input("請輸入命令>>:").strip()if len(cmd) == 0:continue #如果長度為0,就繼續返回循環client.send(cmd.encode('utf-8')) #發送命令(byte)cmd_res_size = client.recv(1024) #接受返回數據的大小print("接受的數據",cmd_res_size) #打印接收大小received_size = 0received_data = b''while received_size < int(cmd_res_size.decode()): #只要不相等就一直收data = client.recv(1024)received_size += len(data) #每次接收到的數據有可能小于1024,所以要用len判斷received_data += data #每次讀取進來的data寫入received_data# print(data.decode())else:print("cmd rees received done",received_size)print(received_data.decode()) client.close() #關閉連接 View Code?
server:
#!/usr/bin/env python # -*- coding:utf-8 -*- #Author:wanghui import socket,osserver = socket.socket() #申明實例 server.bind(('localhost',9999)) #綁定ip和端口 server.listen() #等待連接while True:conn,addr= server.accept() #監聽print("開始連接啦",addr)while True: #正式接受數據啦print("等待新指令:")data = conn.recv(1024) #定義傳輸大小if not data: #如果客戶端斷開,那么就退出此次接收,重新回到監聽狀態print("客戶端已經斷開!")breakprint("執行命令",data)cmd_res = os.popen(data.decode()).read() #讀取客戶端命令(bytes轉換成str)print("接受之前:",len(cmd_res))if len(cmd_res) == 0:cmd_res = "cmd has no output ..."conn.send(str(len(cmd_res.encode())).encode('utf-8')) #先發大小給客戶端conn.send(cmd_res.encode('utf-8')) #向客戶端發送數據,必須是bytesprint("發送完成!") server.close() #斷開連接 View Code?
3.粘包問題
server連續調用send的時候緩沖區會將挨著的兩次操作發給客戶端,導致兩次send的內容都同時發給了客戶端,所以其中的一個方法就是在服務器端的send之間加入sleep時間,可以解決這個問題
? ? ?server:
#!/usr/bin/env python # -*- coding:utf-8 -*- #Author:wanghui import socket,os,timeserver = socket.socket() #申明實例 server.bind(('localhost',9999)) #綁定ip和端口 server.listen() #等待連接while True:conn,addr= server.accept() #監聽print("開始連接啦",addr)while True: #正式接受數據啦print("等待新指令:")data = conn.recv(1024) #定義傳輸大小if not data: #如果客戶端斷開,那么就退出此次接收,重新回到監聽狀態print("客戶端已經斷開!")breakprint("執行命令",data)cmd_res = os.popen(data.decode()).read() #讀取客戶端命令(bytes轉換成str)print("接受之前:",len(cmd_res))if len(cmd_res) == 0:cmd_res = "cmd has no output ..."conn.send(str(len(cmd_res.encode())).encode('utf-8')) #先發大小給客戶端#time.sleep(0.5) #防止粘包的一種方法client_ack= conn.recv(1024) #等待確認print('ack from client:',client_ack)conn.send(cmd_res.encode('utf-8')) #向客戶端發送數據,必須是bytesprint("發送完成!") server.close() #斷開連接client:
#!/usr/bin/env python # -*- coding:utf-8 -*- #Author:wanghui import socket,os client = socket.socket() #實例化socket client.connect(("localhost",9999)) #開始連接啦while True: #發送數據啦cmd = input("請輸入命令>>:").strip()if len(cmd) == 0:continue #如果長度為0,就繼續返回循環client.send(cmd.encode('utf-8')) #發送命令(byte)cmd_res_size = client.recv(1024) #接受返回數據的大小print("接受的數據",cmd_res_size) #打印接收大小client.send("準備確認啦".encode('utf-8'))received_size = 0received_data = b''while received_size < int(cmd_res_size.decode()): #只要不相等就一直收data = client.recv(1024)received_size += len(data) #每次接收到的數據有可能小于1024,所以要用len判斷received_data += data #每次讀取進來的data寫入received_data# print(data.decode())else:print("cmd rees received done",received_size)print(received_data.decode()) client.close() #關閉連接4.簡易的文件傳輸案例
server端的設計:
-
-
- 讀取文件名
- 檢測文件是否存在
- 打開文件
- 檢測文件大小
- 發送文件大小和MD5值給客戶端
- 等待客戶端確認
- 開始邊讀取邊發數據
-
client端:
#!/usr/bin/env python # -*- coding:utf-8 -*- #Author:wanghui import socket,os,hashlibclient = socket.socket() #實例化socket client.connect(("localhost",9999)) #開始連接啦while True: #發送數據啦cmd = input(">>:").strip()if len(cmd) == 0:continue #如果長度為0,就繼續返回循環if cmd.startwith('get'): #定義開始client.send(cmd.encode()) #客戶端發送命令server_resbonce = client.recv(1024) #接收服務器端數據print("server resbonce:",server_resbonce)client.send("準備接收文件".encode())file_total_size = int(server_resbonce.decode()) #定義接受的文件總大小received_size=0 #初始接收文件filename = cmd.split()[1] #獲取文件名f = open(filename + '.new','wb') #開始寫文件m = hashlib.md5() #定義MD5加密while received_size < file_total_size: #如果接收的文件小于總文件大小,就執行如下data = client.recv(1024) #定義接收文件received_size+=len(data) #接受的文件大小變化m.update(data) #生成客戶端接受的MD5f.write(data) #寫入數據#print(file_total_size,received_size) #打印文件接受大小和總大小else:new_file_md5 = m.hexdigest()print("接受完了文件:",file_total_size,received_size)f.close() #關閉文件server_md5 = client.recv(1024) #接收服務器端MD5print(server_md5,new_file_md5) #對比MD5client.close()
?
轉載于:https://www.cnblogs.com/wanghui1991/p/5865848.html
總結
以上是生活随笔為你收集整理的【python自动化第八篇:网络编程】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java9-6 内部类
- 下一篇: 2016 大连网赛---Differen