Python TCP简易版文件传输代码

简介

感觉没有特别顺手的临时文件传输程序。写个demo试试。
代码可以做客户端也可以做服务端。
做为服务器端时,客户端可以发送文件给服务端,也可以从服务端获取文件。

环境

  1. 系统:win10(兼容Linux)
  2. Python:Python 3.8.1(兼容Python 2.7)

使用说明

作为服务端

命令格式:python demo.py server {server_ip} {server_port}

  1. server:server模式
  2. server_ip:服务端地址
  3. server_port:服务端端口(自己随便设置)
    例:python demo.py server 127.0.0.1 8000

作为客户端

命令格式:python demo.py client {server_ip} {server_port} { sendfile source_fullpath taget_filename| recvfile taget_filename storage_fullpath | exit }

  1. client:client模式
  2. server_ip:服务端地址(与server对应)
  3. server_port:服务端端口(与server对应)
  4. sendfile source_fullpath taget_filename:从客户端向服务端发送文件,客户端文件全路径,将保存在服务端上的文件名
    例:python demo.py client 127.0.0.1 8000 sendfile D:/123.txt 456.txt(发送客户端D:/123.txt到服务端demo.py同目录下456.txt)
  5. recvfile taget_filename storage_fullpath:从服务端获取文件,服务端文件名,将保存在客户端上的文件全路径
    例:python demo.py client 127.0.0.1 8000 recvfile 456.txt D:/123.txt(接收服务端demo.py同目录下456.txt到客户端D:/123.txt)
  6. exit:退出服务端

demo代码

demo.py

# coding: utf-8
# 20200627 by
import socket
import sys
import os

def get_script_path():
    return os.path.split(os.path.realpath(__file__))[0]

# 正向接收文字
def s_00(conn): 
    data_len = int(conn.recv(10).decode('utf-8'))
    data = b''
    cache_size = 35
    if data_len % cache_size == 0:
        cache_size += 1
    for i in range(int(data_len / cache_size) + 1):
        data += conn.recv(cache_size)
    print(data.decode('utf-8') + '\n')
    return True

# 正向接收文件
def s_01(conn): 
    filename_len = int(conn.recv(10).decode('utf-8'))
    filename = conn.recv(filename_len).decode('utf-8')
    print('[+] Recv file: {filename}'.format(filename=filename))
    f = open('{path}/{filename}'.format(path=get_script_path(), filename=filename),'wb')
    while True:
        data = conn.recv(1024)
        if not data:
            break
        f.write(data)
    f.close()

# 反向发送文字
def s_10(conn):
    pass

# 反向发送文件
def s_11(conn):
    filename_len = int(conn.recv(10).decode('utf-8'))
    filename = conn.recv(filename_len).decode('utf-8')
    print('[+] Send file: {filename}'.format(filename=filename))
    f = open('{path}/{filename}'.format(path=get_script_path(), filename=filename), 'rb')
    while True:
        data = f.read(1024)
        if not data:
            break
        conn.send(data)
    f.close()

def server(host, port):

    server_handle = {
        '00': s_00,
        '01': s_01,
        '10': s_10,
        '11': s_11,
    }

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind((str(host), int(port)))
    s.listen(1)

    while True:
        # 等待连接后分配会话,获取地址addr[0]
        conn, addr = s.accept()
        print('[+] Accept source address: {addr}'.format(addr=addr[0]))
        # 等待数据
        handle = conn.recv(2).decode('utf-8')
        # 格式:^(?P<模式>d)(?P<数据类型>d)(?P<数据长度>d{10})(?P<数据>d)
        #   1. 模式:       
        #               0. 正向模式
        #               1. 反向模式
        #   2. 数据类型:
        #               0. 文字
        #               1. 文件
        #   3. 数据长度:
        #               文字长度/文件名长度
        #   4. 数据:
        #               二进制数据
        if handle == '':
            conn.close()
            continue

        fun = server_handle.get(handle, None)
        if fun == None and handle != '':
            break
        fun(conn)
        conn.close()

    s.close()


# 发送文字
def c_00(s):
    data = sys.argv[5]
    data_len = str(len(data.encode('utf-8'))).zfill(10)
    string = '00' + data_len + data
    s.send(string.encode('utf-8'))

# 发送文件
# source_fullpath 456.txt
def c_01(s):
    mode = '01'.encode('utf-8')
    source_fullpath = sys.argv[5]
    filename = sys.argv[6].encode('utf-8')
    filename_len = str(len(filename)).zfill(10).encode('utf-8')
    s.send(mode + filename_len + filename)
    f = open(source_fullpath, 'rb')
    while True:
        data = f.read(1024)
        if not data:
            break
        s.send(data)
    f.close()

# 获取文字
def c_10(s):
    pass

# 获取文件
# taget_filename.txt D:/456.txt
def c_11(s):
    mode = '11'.encode('utf-8')
    taget_filename = sys.argv[5].encode('utf-8')
    taget_filename_len = str(len(taget_filename)).zfill(10).encode('utf-8')
    storage_fullpath = sys.argv[6]
    f = open(storage_fullpath, 'wb')
    s.send(mode + taget_filename_len + taget_filename)
    while True:
        data = s.recv(1024)
        if not data:
            break
        f.write(data)
    f.close()

def c_12(s):
    mode = '12'.encode('utf-8')
    s.send(mode)

def client(host, port):
    client_handle = {
        'sendinfo': c_00,
        'sendfile': c_01,
        'recvinfo': c_10,
        'recvfile': c_11,
        'exit': c_12
    }

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((str(host), int(port)))

    fun = client_handle.get(sys.argv[4], None)
    if fun == None:
        print('[-] Unknown command: {command}'.format(command=sys.argv[4]))
    else:
        fun(s)

    s.close()

if __name__ == "__main__":
    
    mode = {
        'server': server,
        'client': client
    }

    host = sys.argv[2]
    port = sys.argv[3]

    fun = mode.get(sys.argv[1], None)
    if fun != None:
        fun(host, port)

你可能感兴趣的:(Python TCP简易版文件传输代码)