在python中通过TCP套接字在客户端 - 服务器之间发送文件?

时间:2015-03-15 07:10:46

标签: python sockets tcp client-server

我正在尝试通过TCP套接字发送和接收文件。当用户键入put abc.txt时,应将abc.txt复制到服务器 当用户键入get def.txt时,应将def.txt下载到用户计算机。 (实际上我必须实现另外两个方法 - ls列出客户端目录中的所有文件,lls列出服务器中的所有文件,但我还没有完成。)

这是代码

服务器

import socket
import sys
HOST = 'localhost'                 
PORT = 3820

socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.bind((HOST, PORT))

socket.listen(1)
while (1):
    conn, addr = socket.accept()
    print 'New client connected ..'
    reqCommand = conn.recv(1024)
    print 'Client> %s' %(reqCommand)
    if (reqCommand == 'quit'):
        break
    #elif (reqCommand == lls):
        #list file in server directory
    else:
        string = reqCommand.split(' ', 1)   #in case of 'put' and 'get' method
        reqFile = string[1] 

        if (string[0] == 'put'):
            with open(reqFile, 'wb') as file_to_write:
                while True:
                    data = conn.recv(1024)
                    if not data:
                        break
                    file_to_write.write(data)
                    file_to_write.close()
                    break
            print 'Receive Successful'
        elif (string[0] == 'get'):
            with open(reqFile, 'rb') as file_to_send:
                for data in file_to_send:
                    conn.sendall(data)
            print 'Send Successful'
    conn.close()

socket.close()

客户端

import socket
import sys

HOST = 'localhost'    #server name goes in here
PORT = 3820

def put(commandName):
    socket.send(commandName)
    string = commandName.split(' ', 1)
    inputFile = string[1]
    with open(inputFile, 'rb') as file_to_send:
        for data in file_to_send:
            socket.sendall(data)
    print 'PUT Successful'
    return 

def get(commandName):
    socket.send(commandName)
    string = commandName.split(' ', 1) 
    inputFile = string[1]
    with open(inputFile, 'wb') as file_to_write:
        while True:
            data = socket.recv(1024)
            #print data
            if not data:
                break
            print data
            file_to_write.write(data)
            file_to_write.close()
            break
    print 'GET Successful'
    return

socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.connect((HOST,PORT))

msg = raw_input('Enter your name: ')
while(1):
    print 'Instruction'
    print '"put [filename]" to send the file the server '
    print '"get [filename]" to download the file from the server '
    print '"ls" to list all files in this directory'
    print '"lls" to list all files in the server'
    print '"quit" to exit'
    sys.stdout.write ('%s> ' %msg)
    inputCommand = sys.stdin.readline().strip()
    if (inputCommand == 'quit'):
        socket.send('quit')
        break
    # elif (inputCommand == 'ls')
    # elif (inputCommand == 'lls')
    else:
        string = inputCommand.split(' ', 1)
    if (string[0] == 'put'):
        put(inputCommand)
    elif (string[0] == 'get'):
        get(inputCommand)
socket.close()

我无法解决几个问题。

  1. 该程序仅在第一次正确运行('put'和 'get'方法)。之后,来自客户端的所有命令都不能 发送到服务器。
  2. 'get'方法不适用于图像/照片文件。

1 个答案:

答案 0 :(得分:2)

首先出现问题,因为在处理一个命令后,服务器正在关闭连接。

conn.close()

第二个问题正在发生,因为您没有从客户端的套接字读取所有数据。在while循环结束时,你有一个“break”语句,因为客户端在读取1024字节后才关闭套接字。当服务器尝试在此关闭套接字上发送数据时,它会导致服务器端出错。

while True:
    data = socket1.recv(1024)
    # print data
    if not data:
        break
    # print data
    file_to_write.write(data)
    file_to_write.close()
    break

有两种方法可以解决第一个问题。

  1. 更改客户端,以便为每个命令创建一个新连接&发送命令到服务器。
  2. 更改服务器以通过同一连接处理多个命令。
  3. 以下代码是更改后的客户端,用于演示修复第一个问题的第一种方法。它还解决了第二个问题。

    import socket
    import sys
    
    HOST = 'localhost'    # server name goes in here
    PORT = 3820
    
    
    def put(commandName):
        socket1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        socket1.connect((HOST, PORT))
        socket1.send(commandName)
        string = commandName.split(' ', 1)
        inputFile = string[1]
        with open(inputFile, 'rb') as file_to_send:
            for data in file_to_send:
                socket1.sendall(data)
        print 'PUT Successful'
        socket1.close()
        return
    
    
    def get(commandName):
        socket1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        socket1.connect((HOST, PORT))
        socket1.send(commandName)
        string = commandName.split(' ', 1)
        inputFile = string[1]
        with open(inputFile, 'wb') as file_to_write:
            while True:
                data = socket1.recv(1024)
                # print data
                if not data:
                    break
                # print data
                file_to_write.write(data)
        file_to_write.close()
        print 'GET Successful'
        socket1.close()
        return
    
    
    msg = raw_input('Enter your name: ')
    while(1):
        print 'Instruction'
        print '"put [filename]" to send the file the server '
        print '"get [filename]" to download the file from the server '
        print '"ls" to list all files in this directory'
        print '"lls" to list all files in the server'
        print '"quit" to exit'
        sys.stdout.write('%s> ' % msg)
        inputCommand = sys.stdin.readline().strip()
        if (inputCommand == 'quit'):
            socket.send('quit')
            break
        # elif (inputCommand == 'ls')
        # elif (inputCommand == 'lls')
        else:
            string = inputCommand.split(' ', 1)
            if (string[0] == 'put'):
                put(inputCommand)
            elif (string[0] == 'get'):
                get(inputCommand)