程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

HNU計網實驗:實驗二 網絡基礎編程實驗(JAVA\Python3)

編輯:Python

說些什麼

記得當時做實驗的時候我是滿心的臥槽的,因為實驗一和實驗二簡直是天壤之別,我記得在驗收前的那個下午,我依然在瘋狂改代碼。

眾所周知,我是一個衷心於摸魚的小菜雞,所以我這個代碼其實是我在別人代碼的基礎上改出來的一個,其實理論上我應該bia出來參考的博客的網址的,但是這是好早之前的了我找不到了…

實驗目的

通過本實驗,學習采用Socket(套接字)設計簡單的網絡數據收發程序,理解應用數據包是如何通過傳輸層進行傳送的。

實驗內容

Socket(套接字)是一種抽象層,應用程序通過它來發送和接收數據,就像應用程序打開一個文件句柄,將數據讀寫到穩定的存儲器上一樣。一個socket允許應用程序添加到網絡中,並與處於同一個網絡中的其他應用程序進行通信。一台計算機上的應用程序向socket寫入的信息能夠被另一台計算機上的另一個應用程序讀取,反之亦然。
不同類型的socket與不同類型的底層協議族以及同一協議族中的不同協議棧相關聯。現在TCP/IP協議族中的主要socket類型為流套接字(sockets sockets)和數據報套接字(datagram sockets)。流套接字將TCP作為其端對端協議(底層使用IP協議),提供了一個可信賴的字節流服務。一個TCP/IP流套接字代表了TCP連接的一端。數據報套接字使用UDP協議(底層同樣使用IP協議),提供了一個"盡力而為"(best-effort)的數據報服務,應用程序可以通過它發送最長65500字節的個人信息。一個TCP/IP套接字由一個互聯網地址,一個端對端協議(TCP或UDP協議)以及一個端口號唯一確定。

寫一個簡單的chat程序,並能互傳文件,編程語言不限

客戶端

#客戶端的chat
import socket
import sys
import os
ip_port = ('127.0.0.1',9998) #使用9999會提示被占用?
sk = socket.socket()
sk.connect(ip_port)
container = {
'key':'','data':''} #文件路徑的剪切
while True:
FLAG = input('0.接收文件 1.發送文件 2.進行消息發送\n')
sk.sendall(str(FLAG).encode('utf-8'))
if FLAG=='1': #發送文件,即原本的功能
path = input('path:') # 客戶端輸入要上傳文件的路徑 
path = 'F:\\\\'+path #F盤的test10031.txt
print('哈哈哈哈哈',path) ##################test
file_name = os.path.basename(path) # 根據路徑獲取文件名
file_size=os.stat(path).st_size # 獲取文件大小
Informf=(file_name+'|'+str(file_size)) #客戶端的打包
sk.send(Informf.encode()) # 發送文件名 和 文件大小
# 為了防止粘包,將文件名和大小發送過去之後,等待服務端收到,直到從服務端接受一個信號(說明服務端已經收到)
msg=sk.recv(1024)
print(msg.decode())
send_size = 0
f= open(path,'rb')
Flag = True
while Flag:
if send_size + 1024 >file_size:
data = f.read(file_size-send_size)
Flag = False
else:
data = f.read(1024)
send_size+=1024
sk.send(data)
aaa = sk.recv(1024) #新增接收
print(aaa.decode())
f.close()
elif FLAG=='0' : #接收
message=sk.recv(1024)
print(message.decode(encoding='utf8'))
message = input('path: ')
message = str(message)
# 發送數據 加碼
sk.sendall(message.encode('utf-8'))
print('客戶端等待...')
#之前的Srv
pre_data = sk.recv(1024).decode()
#獲取請求方法、文件名、文件大小
file_name,file_size = pre_data.split('|') #服務器的解包
# 防止粘包,給客戶端發送一個信號。
sk.sendall('收到'.encode())
#已經接收文件的大小
recv_size = 0
file_dir = os.path.join('F:\\\\',message) #下載文件路徑拼接 ####理論上沒錯的樣子
print('嘿嘿嘿嘿嘿',file_dir)
f = open(file_dir,'wb')
Flag = True
while Flag:
#未上傳完畢,
if int(file_size)>recv_size:
#最多接收1024,可能接收的小於1024
data = sk.recv(1024)
recv_size+=len(data)
#寫入文件
f.write(data)
#上傳完畢,則退出循環
else:
recv_size = 0
Flag = False
sk.sendall('下載完成'.encode()) #新增發送
print('接收成功')
f.close()
#Srv至此
else : #進行信息發送
print('開始進行聊天')
while True:
msg = input("> ")
if msg == 'stop':
sk.send('stop'.encode('utf-8')) #客戶端發送停止消息
break
elif not msg:
continue
sk.send(msg.encode('utf-8')) # 客戶端發送消息
rev_data = sk.recv(1024) # 客戶端接受消息
if not rev_data:
break
print('服務器消息:', rev_data.decode('utf-8'))
sk.close()

服務端

#服務端
import socketserver
import os
class MyServer(socketserver.BaseRequestHandler):
def handle(self):
conn = self.request
print ('connected...')
while True:
order = conn.recv(1024).decode(encoding='utf8') #增加讀取
print('執行',order)
if order == '1' : #接收文件,即原本的任務
print('服務器等待...')
pre_data = conn.recv(1024).decode()
#獲取請求方法、文件名、文件大小
file_name,file_size = pre_data.split('|') #服務器的解包
# 防止粘包,給客戶端發送一個信號。
conn.sendall('收到'.encode())
#已經接收文件的大小
recv_size = 0
file_dir = os.path.join('D:\\\\',file_name) #接收的文件路徑拼接 #現在沒錯了
print("啦啦啦啦啦",file_dir) #####test
f = open(file_dir,'wb')
Flag = True
while Flag:
#未上傳完畢,
if int(file_size)>recv_size:
#最多接收1024,可能接收的小於1024
data = conn.recv(1024)
recv_size+=len(data)
#寫入文件
f.write(data)
#上傳完畢,則退出循環
else:
recv_size = 0
Flag = False
conn.sendall('下載完成'.encode()) #添加發送
print('上傳成功')
f.close()
if order == '0' : #發送文件
conn.sendall('服務器准備發送文件'.encode('utf-8'))
#原來的Clt
#path = input('path:') # 客戶端輸入要上傳文件的路徑
path = conn.recv(1024).decode() #這裡路徑是從客戶端讀取的
#file_name = os.path.basename(path) # 根據路徑獲取文件名
file_name = os.path.join('D:\\\\', path) #拼接 ###########理論上沒錯
print('耶耶耶耶耶',file_name)
file_size=os.stat(file_name).st_size # 獲取文件大小
Informf=(file_name+'|'+str(file_size)) # 包裝文件名 和 文件大小
conn.send(Informf.encode()) # 發送
# 為了防止粘包,將文件名和大小發送過去之後,等待服務端收到,直到從服務端接受一個信號(說明服務端已經收到)
bbb=conn.recv(1024).decode()
print(bbb)
send_size = 0
f= open(file_name,'rb')
Flag = True
while Flag:
if send_size + 1024 >file_size:
data = f.read(file_size-send_size)
Flag = False
else:
data = f.read(1024)
send_size+=1024
conn.send(data)
conn.recv(1024) #新增接收
f.close()
if order == '2' :
print('開始進行聊天')
while True:
data = conn.recv(1024) # 接受客戶端發送的消息
print('客戶端消息:', data.decode('utf-8'))
if not data:
continue
elif data.decode() == 'stop':
print('停止聊天')
break
message = input('> ')
conn.send(message.encode('utf-8')) # 客戶端發送消息
instance = socketserver.ThreadingTCPServer(('127.0.0.1',9998),MyServer)
instance.serve_forever()

主要思路就是通過FLAG的值來判斷操作:
FLAG=='1’的時候就是發送文件
FLAG=='0’的時候就是接收文件
FLAG=='2’的時候就是信息互發

有些奇奇怪怪的輸出不需要在意,當時有bug然後de不出來,就想著通過輸出來看在哪一步執行不來…
樸素的程序員往往用最質樸的方法來debug…
我真的會謝…


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved