說明:該篇博客是博主一字一碼編寫的,實屬不易,請尊重原創,謝謝你們!python
目錄編程
一丶項目介紹python3.x
二丶服務器Server服務器
五丶測試客戶端向服務器下載文件socket
1.敘述tcp
生活中你們都使用過迅雷吧,用戶在客戶端上使用迅雷從服務器上download一個文件到客戶端,今天博主就是使用TCP網絡搭建一個客戶端client鏈接服務器server,從服務器server上下載所想要下載的文件到客戶端client上編程語言
2.項目環境函數
操做系統:Windows7
IDE:PyCharm2017
編程語言:python3.x
測試工具:網絡調試工具3.x
1.在PyCharm中建立file_download_tcpServer.py和file_download_tcpClient.py文件用於實現tcp服務器客戶端
2.首先在file_download_tcpServer.py中進行代碼邏輯編寫
tcp_server_socket = socket(AF_INET, SOCK_STREAM)
tcp_server_socket.bind(('', 8888))
tcp_server_socket.listen(128)
client_socket, clientAddr = tcp_server_socket.accept()
print("用戶%s 已鏈接"% str(clientAddr))
recv_data = client_socket.recv(1024) # 接收1024個字節 file_name = recv_data.decode("utf-8") print("對方請求下載的文件名爲:%s" % file_name)
try: with open(filename, "rb") as f: file_content = f.read() except Exception as e: print("獲取文件內容出錯:", e) if file_content: client_socket.send(file_content) # 關閉該套接字 client_socket.close()
tcp_server_socket.close()
3.封裝(解耦)代碼,博主之因此這樣作,是爲了讓你們瞭解一個正確開發過程,提升代碼複用性
從上面代碼能夠看出耦合性比較嚴重,看着雜亂無章比較費勁,因此須要對代碼進行解耦操做,下降代碼耦合性,獲取客戶端下載文件內容能夠封裝到一個方法裏(get_file_content),而tcp 服務器建立套接字以及關閉均可以封裝到main方法裏面,以下所示
def get_file_content(filename): """獲取文件內容""" try: with open(filename, "rb") as f: content = f.read() return content except Exception as e: print("獲取文件內容出錯:", e) def main(): # 建立socket tcp_server_socket = socket(AF_INET, SOCK_STREAM) # 綁定本地信息 tcp_server_socket.bind(('', 8888)) # 使用listen將主動套接字變爲被動套接字 tcp_server_socket.listen(128) while True: # 等待客戶端的連接,即爲這個客戶端發送文件 client_socket, clientAddr = tcp_server_socket.accept() print("用戶%s 已鏈接"% str(clientAddr)) # 接收客戶端發送過來的數據獲取客戶要下載的文件名 recv_data = client_socket.recv(1024) # 接收1024個字節 file_name = recv_data.decode("utf-8") print("對方請求下載的文件名爲:%s" % file_name) file_content = get_file_content(file_name) # 發送文件的數據給客戶端,獲取文件內容使用rb二進制,因此這裏不須要進行encode編碼操做 if file_content: client_socket.send(file_content) # 關閉客戶端套接字 client_socket.close() # 關閉服務器監聽套接字 tcp_server_socket.close() if __name__ == "__main__": main()
4. 指定服務器運行方式爲python3 xxx.py 8888,將服務器綁定端口號傳入到代碼中
import sys print(len(sys.argv))
def main(): import sys if len(sys.argv) != 2: print("請按照以下方式運行:python3 xxx.py 8888") return else: # 運行方式爲python3 xxx.py 8888 port = int(sys.argv[1]) # 8888
1.在Terminal終端執行python3 file_download_tcpServer.py 沒有傳入端口號,出現定義的提示
2.在Terminal終端執行python3 file_download_tcpServer.py 8888即成功運行tcp 服務器並綁定8888端口,終端光標開始閃爍等待客戶端的鏈接
3.打開網絡調試助手,選擇TCP client客戶端,IP地址爲本機IP 端口爲服務器綁定端口號8888,
4.點擊鏈接成功後,回到pycharm Terminal終端,此時終端顯示用戶XXXX已鏈接
5.在網絡調試助手中發送demo.py文件名(client發送下載文件名必須存在於服務器端),此時服務器獲取客戶端發送的下載文件名,獲取該文件的內容發送給客戶端,表明服務器代碼邏輯編寫正確
1.在file_download_tcpClient.py中進行代碼邏輯編寫,相對服務器來講客戶端的代碼實現就比較簡單,首先定義main主函數用於客戶端建立套接字鏈接目標服務器
tcp_client_socket = socket(AF_INET, SOCK_STREAM)
tcp_client_socket.connect((input("請輸入服務器ip:"), int(input("請輸入服務器port:"))))
file_name = input("請輸入要下載的文件名:") tcp_client_socket.send(file_name.encode("utf-8"))
recv_data = tcp_client_socket.recv(1024)
if recv_data: with open("[接收]"+file_name, "wb") as f: f.write(recv_data)
tcp_client_socket.close()
2.客戶端完整代碼
from socket import * def main(): # 建立socket套接字 tcp_client_socket = socket(AF_INET, SOCK_STREAM) # 鏈接目標服務器 tcp_client_socket.connect((input("請輸入服務器ip:"), int(input("請輸入服務器port:")))) # 輸入須要下載的文件名 file_name = input("請輸入要下載的文件名:") # 向服務器發送文件下載請求 tcp_client_socket.send(file_name.encode("utf-8")) # 接收服務器發送過來的數據 recv_data = tcp_client_socket.recv(1024) print('接收到的數據爲:', recv_data.decode('utf-8')) # 接收數據不爲空時,寫入到本地客戶端, if recv_data: with open("[接收]"+file_name, "wb") as f: f.write(recv_data) # 關閉套接字 tcp_client_socket.close() if __name__ == "__main__": main()
1.首先在Terminal終端上執行python3 file_download_tcpServer.py 8888將服務器運行在8888端口上,此時服務器正等待客戶端鏈接
2.在pycharm上直接run運行 file_download_tcpClient.py客戶端
3.在服務器目錄下存放一張1.jpg頭像圖片,進行測試
recv_data = tcp_client_socket.recv(100000)