简体   繁体   English

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

[英]Sending files between client - server through TCP socket in python?

I'm trying to send and receive files through a TCP socket. 我正在尝试通过TCP套接字发送和接收文件。 When user types put abc.txt , abc.txt should be copied to the server. 当用户输入put abc.txt ,应将abc.txt复制到服务器。
When user types get def.txt , def.txt should be downloaded to the user computer. 当用户类型get def.txt ,应将def.txt下载到用户计算机。 (Actually I have to implement 2 more methods - ls to list all files in the client directory and lls to list all files in the server, but I haven't done it yet.) (实际上,我还必须实现2种方法lls列出客户端目录中的所有文件, ls列出服务器中的所有文件,但是我还没有这样做。)

Here's the code 这是代码

Server 服务器

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()

Client 客户

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()

There are several problems that I couldn't fix. 我无法解决几个问题。

  1. The program run correctly only on the first time (both 'put' and 'get' method). 该程序仅在第一次时正确运行(“ put”和“ get”方法)。 After that, All commands from the client can't be sent to the server. 此后,无法将来自客户端的所有命令发送到服务器。
  2. The 'get' method doesn't work for an image/photo file. “获取”方法不适用于图像/照片文件。

First problem is occurring because after handling one command, server is closing the connection. 发生第一个问题是因为在处理一个命令后,服务器正在关闭连接。

conn.close()

Second problem is occurring because you are not reading all the data from the socket in client. 发生第二个问题是因为您没有从客户端的套接字读取所有数据。 At the end of while loop you have a "break" statement, due to which client is closing the socket just after reading 1024 bytes. 在while循环的末尾,您有一个“ break”语句,由于该语句,客户机在读取1024个字节后才关闭套接字。 And when server tries to send data on this close socket, its results in error on the server side. 当服务器尝试在此关闭的套接字上发送数据时,它会在服务器端导致错误。

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

There are two ways to fix this first issue. 有两种方法可以解决第一个问题。

  1. Change the client so that for each command it creates a new connection & sends command to the server. 更改客户端,以便为每个命令创建一个新连接并将命令发送到服务器。
  2. Change the server to handle multiple commands over the same connection. 更改服务器以在同一连接上处理多个命令。

Following code is the changed client to demonstrate the first way to fix the first issue. 以下代码是更改后的客户端,以演示解决第一个问题的第一种方法。 It also fixes the second issue. 它还解决了第二个问题。

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM