使用網絡TCP搭建一個簡單文件下載器

說明:該篇博客是博主一字一碼編寫的,實屬不易,請尊重原創,謝謝你們!python

目錄編程

一丶項目介紹python3.x

二丶服務器Server服務器

三丶測試TCP server服務器網絡

四丶客戶端Client併發

五丶測試客戶端向服務器下載文件socket


一丶項目介紹

1.敘述tcp

生活中你們都使用過迅雷吧,用戶在客戶端上使用迅雷從服務器上download一個文件到客戶端,今天博主就是使用TCP網絡搭建一個客戶端client鏈接服務器server,從服務器server上下載所想要下載的文件到客戶端client上編程語言

2.項目環境函數

操做系統:Windows7 

IDE:PyCharm2017

編程語言:python3.x

測試工具:網絡調試工具3.x

二丶服務器Server

1.在PyCharm中建立file_download_tcpServer.py和file_download_tcpClient.py文件用於實現tcp服務器客戶端

2.首先在file_download_tcpServer.py中進行代碼邏輯編寫

  • step1 建立tcp socket套接字
tcp_server_socket = socket(AF_INET, SOCK_STREAM)
  • step2 綁定本地IP和端口
tcp_server_socket.bind(('', 8888))
  • step3 使用listen將主動套接字變爲被動套接字
tcp_server_socket.listen(128)
  • step4 等待客戶端的連接,即爲這個客戶端發送文件,由於不止一個客戶鏈接,此時須要將(step4~7)代碼寫在while True裏面
client_socket, clientAddr = tcp_server_socket.accept()
  • step5 顯示鏈接的客戶端用戶信息
print("用戶%s 已鏈接"% str(clientAddr))
  • step6 接收客戶端發送過來的數據獲取客戶要下載的文件,並打印顯示
recv_data = client_socket.recv(1024)  # 接收1024個字節
file_name = recv_data.decode("utf-8")
print("對方請求下載的文件名爲:%s" % file_name)
  • step7 根據客戶請求下載的文件名,獲取該文件內容,併發送給客戶端
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()
  • step8 關閉服務器監聽套接字
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,將服務器綁定端口號傳入到代碼中

  • step1 指定TCP服務器啓動爲終端命令python3 xxx.py 8888方式,這個比較新穎,這裏博主給你們詳細進行演示,這裏博主在項目目錄下建立demo.py文件用於演示,在demo.py中進行以下編寫
import sys
print(len(sys.argv))
  • step2 在pycharm中直接運行run demo.py結果以下

  • step3 在pycharm Terminal終端執行python3 demo.py 8888 ,打印出sys.argv的長度爲2,結果爲列表因此打印的第一個元素值爲文件名第二元素的值爲傳入的端口號,因此說若是sys.argv的長度爲1表明直接運行,爲2時表示是以python3 xxx.py 8888方式運行,由此能夠進行邏輯判斷

 

  • step4 在main主函數第一行加入如下代碼,並將bing方法中的端口參數修改成port
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

 三丶測試TCP server服務器

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發送下載文件名必須存在於服務器端),此時服務器獲取客戶端發送的下載文件名,獲取該文件的內容發送給客戶端,表明服務器代碼邏輯編寫正確

  • step1 服務端顯示以下

  • step2 客戶端顯示以下 

 四丶客戶端Client

1.在file_download_tcpClient.py中進行代碼邏輯編寫,相對服務器來講客戶端的代碼實現就比較簡單,首先定義main主函數用於客戶端建立套接字鏈接目標服務器

  • step1 建立套接字
tcp_client_socket = socket(AF_INET, SOCK_STREAM)
  • step2 鏈接目標服務器
tcp_client_socket.connect((input("請輸入服務器ip:"), int(input("請輸入服務器port:"))))
  • step3 輸入要下載的文件名,並向服務器發送
file_name = input("請輸入要下載的文件名:")
tcp_client_socket.send(file_name.encode("utf-8"))
  • step4 接收服務器發送過來的數據,接收1024個字節(1K)
recv_data = tcp_client_socket.recv(1024)
  • step5 接收數據不爲空時,寫入到本地客戶端
if recv_data:
    with open("[接收]"+file_name, "wb") as f:
        f.write(recv_data)
  • step6 關閉客戶端套接字
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客戶端

  • step1 運行後則顯示輸入服務器的IP,端口以及要下載的文件名,發送請求給服務器成功則服務器會將該文件的內容發送給客戶端,此時打印出demo.py文件中的內容,並在本地客戶端成功建立一個[接收]demo.py文件

  • step2 查看是否存在 [接收]demo.py文件

  • step3 查看該文件內容,與demo.py內容一致表示從服務器下載文件成功

  • step4 查看Terminal服務器顯示,顯示出客戶端請求下載的文件名正確

3.在服務器目錄下存放一張1.jpg頭像圖片,進行測試

  • step1 查看1.jpg文件

  • step2 由於該圖片大小爲42.04K所在在客戶端中recv方法的參數值必須大於文件大小值,因此這裏我修改成100000,1024=1k,否則的話下載的圖片會出現模糊以及殘缺
recv_data = tcp_client_socket.recv(100000)
  • step3 運行file_download_tcpClient.py程序,向服務器發送下載1.jpg文件請求,

  • step4  查看下載後的[接收]1.jpg文件並與1.jpg文件進行對比,屬性均一致,表示搭建的tcp文件下載器成功

相關文章
相關標籤/搜索