學號 2019-2020-2 《Python程序設計》實驗3報告
課程:《Python程序設計》
班級:1924
姓名: 萬騰陽
學號:20192419
實驗教師:王志強
實驗日期:2020年5月16日
必修/選修: 公選課
1.實驗內容
創建服務端和客戶端,服務端在特定端口監聽多個客戶請求。客戶端和服務端通過Socket套接字(TCP/UDP)進行通信。
2. 實驗過程及結果
先引入socket 庫,隨后還需要os,struct,sys等,由于這里使用的是base64加密,所以需要引入base64庫進行加密。準備工作做完了,就開始建立連接了。建立連接時要找出沒有被占有的端口,否則無法連接。同時還要找到可使用的IP地址連接完畢后就可以傳輸文件了。
服務器端:
先是等待請求并接受(程序會停留在這一旦收到連接請求即開啟接受數據的線程),接收數據,收到請求后回復,申請相同大小的空間存放發送過來的文件名與文件大小信息,接收文件名與文件大小信息,判斷是否接收到文件頭信息,獲取文件名和文件大小,將分批次傳輸的二進制流依次寫入到文件,此時文件應為base64 傳輸結束記得斷開連接避免出現錯誤。
客戶端:
創建套接字對象 ‘s’,建立需要傳輸的文件路徑,定義定義文件信息。128s表示文件名為128bytes長,l表示一個int或log文件類型,在此為文件大小,將文件進行base64加密,將傳輸文件以二進制的形式分多次上傳至服務器,之后關閉套接字對象。
客戶端代碼:
import socket
import os
import sys
import struct
import base64
f_org = open(r'D:\qwer.txt', 'r')
content = f_org.read()
content1 = content.encode(encoding='utf-8')
content2 = base64.b64encode(content1)
f_org.close()
with open(r'D:\qwer.txt', 'wb+') as f_org:
f_org.write(content2)
print("have encrypted,the ciphertext is:"+ str(content2))
def socket_client():
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('127.0.0.1', 9001))
except socket.error as msg:
print(msg)
sys.exit(1)
print(s.recv(1024))
filepath = r'D:\qwer.txt'
if os.path.isfile(filepath):
fileinfo_size = struct.calcsize('128sl')
fhead = struct.pack('128sl', os.path.basename(filepath).encode('utf-8'), os.stat(filepath).st_size)
s.send(fhead)
fp = open(filepath, 'rb')
while 1:
data = fp.read(1024)
if not data:
print('{0} file send over...'.format(os.path.basename(filepath)))
break
s.send(data)
s.close()
if __name__ == '__main__':
socket_client()
服務器端代碼:
import sys
import os
import base64
def socket_service():
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('127.0.0.1', 9001))
s.listen(10)
except socket.error as msg:
print(msg)
sys.exit(1)
print('Waiting connection...')
while 1:
conn, addr = s.accept()
t = threading.Thread(target=deal_data, args=(conn, addr))
t.start()
def deal_data(conn, addr):
print('Accept new connection from {0}'.format(addr))
conn.send('Hi, Welcome to the server!'.encode('utf-8'))
while 1:
fileinfo_size = struct.calcsize('128sl')
buf = conn.recv(fileinfo_size)
if buf:
filename, filesize = struct.unpack('128sl', buf)
fn = filename.strip(b'\00')
fn = fn.decode()
print('file new name is {0}, filesize if {1}'.format(str(fn), filesize))
recvd_size = 0
os.chdir(r"C:\Users\86186\Desktop")
fp = open('./' + str(fn), 'wb')
print('start receiving...')
while not recvd_size == filesize:
if filesize - recvd_size > 1024:
data = conn.recv(1024)
recvd_size += len(data)
else:
data = conn.recv(filesize - recvd_size)
recvd_size = filesize
fp.write(data)
url = data
str_url = base64.b64decode(url).decode("utf-8")
file = open(r'C:\Users\86186\Desktop'+'./' +str(fn) , 'w+')
file.write(str_url)
fp.close()
print('end receive...')
conn.close()
break
if __name__ == "__main__":
socket_service()
部分運行結果:
3. 實驗過程中遇到的問題和解決過程
之前有一次搭建服務器時,我想試著用自己的IP地址,然后上網去找,找到后就直接運行了客戶端,隨后一直被服務器拒取。
后來才發現我忘記先運行服務器了。
隨后的加密文件讓我陷入了苦惱,python庫中含有哈希值加密,但后面去查找,竟然沒有用哈希值解密這樣的貼子。然后我只能采取了base64加密,說是加密其實也算是一種偽加密,它只是換了一種編碼方式而已,任何人通過python中的base64庫進行解密。
其他(感悟、思考等)
這次實驗因為還沒有學習服務器的相關知識,大多數都是靠著百度完善的代碼。要想熟練運用python必須多實踐,多編寫代碼,這樣運用起來就輕松很多。當然,做實驗前還需要把每個細節弄清楚,弄明白,實驗后,還要復習,思考,這樣印象深刻,記得才牢固,否則實驗后就會忘得一干二凈,這還不如不做。
透過這次實驗我學到了不少知識,更重要的事,做實驗的過程,思考問題的方法,這與做其他的實驗是通用的,真正使我們受益匪淺。