Zanis Ali
Zanis Ali

Reputation: 74

Tcp sockets to send and receive files, using python

I am trying to make simple client server program to send and receive file form server using tcp sockets. As far as getting files from server is not an issue, server creates a file with the same name and put data in that file but when it comes to putting files to server,sometimes it works great but always chance so mostly server is getting file name along with file contents and instead of writing that to file, it writes both filename and contents as new file name and that file remains empty. Will be great help if someone can suggest any solution.

server.py

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:
                data=conn.recv(1024)
                while True:
                    if not data:
                        break
                    else:
                        file_to_write.write(data)
                        data=conn.recv(1024)
                    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.py

    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('clientfolder/'+inputFile, 'rb') as file_to_send:
        data=file_to_send.read(1024)
        while(data):
            socket1.send(data)
            data=file_to_send.read(1024)
            file_to_send.close()
    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('clientfolder/'+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)
#current working directory is server location
#get will get file from current directory to clientfolder directory.

Upvotes: 0

Views: 4244

Answers (1)

Mark Tolonen
Mark Tolonen

Reputation: 177406

TCP is a streaming protocol, so you have to design message breaks into your protocol. For example:

s.send('put filename')
s.send('data')

Can be received as:

s.recv(1024)
# 'put filenamedata'

So buffer data received and only extract full messages. One way is to send the size of a message before the message.

Upvotes: 1

Related Questions