-2

When I start the program to share files to client it received it but when i request for another file download it failed with this error.

 Now i keep getting this error from the client
 socket1.send(bytes('0', 'UTF-8'))
 BrokenPipeError: [Errno 32] Broken pipe
 line 46 client.py

I tried breaking out of the server's filedownload loop but still not working. server

    #! /usr/bin/env python3

    import socket
    import sys
    import os
    import hashlib
    import time

    HOST = 127.0.0.1
    PORT = 5000
    c = 0 #used to count cycles
    bufsize = 4096


    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        print('Server Created')
    except OSError as e:
        print('Failed to create socket. Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
        sys.exit()

    try:
        s.bind((HOST, PORT))
    except OSError as e:
        print('Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1])
        sys.exit()
    print('Socket bind complete')

    s.listen(1)
    print('Server now listening')

    while 1:
        conn, addr = s.accept()
        print('Connected with ' + addr[0] + ':' + str(addr[1]))
        reqCommand = conn.recv(1024).decode("utf-8", errors='ignore')
        print('Client> %s' % reqCommand)
        string = reqCommand.split(' ', 1)
        if reqCommand == 'quit':
            break
        elif reqCommand == 'lls':
            toSend = ""
            path = os.getcwd()
            dirs = os.listdir(path)
            for f in dirs:
                toSend = toSend + f + ' '
            conn.send(toSend.encode('utf-8'))
            # print path


        else:
            string = reqCommand.split(' ', 1)  # in case of 'put' and 'get' method
            if len(string) > 1:
                reqFile = string[1]

                if string[0] == 'FileDownload':
                    with open(reqFile, 'rb') as file_to_send1:
                        # get the entire filesize, which sets the read sector to EOF
                        file_size = len(file_to_send1.read())
                        # reset the read file sector to the start of the file
                        file_to_send1.seek(0)
                        # take filesize and write it to a temp file
                        with open('temp01',mode='w', encoding='UTF-8') as file_to_send2:
                            file_to_send2.write(str(file_size))
                        # pass the file size over to client in a small info chunk
                        with open('temp01', 'rb') as file_to_send3:
                            conn.send(file_to_send3.read(1024))
                        #send the total file size off the client
                        while (c*bufsize) < file_size:
                            send_data = file_to_send1.read(bufsize)
                            conn.send(send_data)
                            c += 1
                            # get bool (0 is bad | 1 is good) from client
                            chunk_write_flag = int(conn.recv(1024))
                            while chunk_write_flag != 1: #while whole data was not sent..retry until successful
                                conn.send(send_data)
                                #get status from client after a retry
                                chunk_write_flag = int(conn.recv(1024))
                            # used on the last chunk of the file xfer
                            # if the file.read() is less than buffer size do last tasks
                            if (file_size - (c*bufsize)) < bufsize:
                                send_data = file_to_send1.read(bufsize)
                                conn.send(send_data)
                                file_to_send1.close()
                            break
                        #for data in file_to_send:
                            #conn.sendall(data)
                    print('Send Successful')
        conn.close()
    s.close()

client

   #! /usr/bin/env python3


    import socket
    import sys
    import os
    import hashlib
    import time


    HOST = 127.0.0.1
    PORT = 5000
    c = 0
    bufsize = 4096


    def get(commandName):
        socket1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        socket1.connect((HOST, PORT))
        socket1.send(commandName.encode("utf-8"))
        string = commandName.split(' ', 1)
        inputFile = string[1]
        c = 0
        # before starting to write new file, get file size
        file_size = int(socket1.recv(1024)) # from file_to_send3
        # print (file_size)
        # set byte buffer size
        bufsize = 4096
        # start writing at the beginning and use following variable to track
        write_sectors = 0
        # this only opens the file, the while loop controls when to close
        with open(inputFile, 'wb+') as file_to_write:
            # while written bytes to out is less than file_size
            while write_sectors < file_size:
                # write the BUFSIZE while the write_sector is less than file_size
                file_to_write.write(socket1.recv(bufsize))
                c += 1
                with open(inputFile, 'rb') as verify:
                    write_check = (len(verify.read()) / c)
                    verify.seek(0) # read cycle moves seek location, reset it
                    while write_check != bufsize:
                        # where the original write started, to send back to server
                        if c > 1: file_to_write.seek((c-1) * bufsize)
                        if c == 1: file_to_write.seek(0)
                        # send to server that the write was not successful
                        socket1.send(bytes('0', 'UTF-8'))
                        file_to_write.write(socket1.recv(bufsize))
                        write_check = int(len(verify.read()) /c )
                        # if last packet, smaller than bufsize
                    socket1.send(bytes('1', 'UTF-8')) #send SUCCESS back to server
                if (file_size - (write_check * c)) < bufsize:
                    #file_to_write.write(socket1.recv(bufsize))
                    verify.close()
                    #file_to_write.close()
                    file_size = 0
                write_sectors += bufsize # successful write, move 'while' check
                # add the written sectors by the bufsize.
                # example if filesize in bytes is 4096 you need to track how much
                # was written to figure out where the EOF  is
            file_to_write.write(socket1.recv(bufsize)) # write the last chunk missed by while loop
                #data = socket1.recv(4096).decode("utf-8", errors="ignore")
                #if not data: break
                    #break
                # print data
                #file_to_write.write(bytes(data.encode()))
            #file_to_write.close()
        print('Download Successful')
        socket1.close()
        return

                  def serverList(commandName):
        socket1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        socket1.connect((HOST, PORT))
        socket1.send(commandName.encode('utf-8'))
        fileStr = socket1.recv(1024)
        fileList = fileStr.decode('utf-8').split(' ')
        for f in fileList:
            print(f)

        socket1.close()
        return


    msg = input('Enter your name: ')
    while 1:
        print("\n")
        print('"FileDownload [filename]" to download the file from the server ')
        print('"lls" to list all files in the server')
        sys.stdout.write('%s> ' % msg)
        inputCommand = sys.stdin.readline().strip()

            if inputCommand == 'lls':
            serverList('lls')

        else:
            string = inputCommand.split(' ', 1)
            if string[0] == 'FileDownload':

Please can anyone help me,i don't know to fix it. I'll appreciate any help. Thanks

Jaiyeola
  • 17
  • 5
  • 1
    This is a lot of code. Please post a [mcve] instead. – ForceBru May 26 '19 at 12:41
  • let me reduce the code – Jaiyeola May 26 '19 at 12:50
  • on which line you are getting this error – vb_rises May 26 '19 at 13:06
  • I'd start with having the client and the server use the same port ;) – Finomnis May 26 '19 at 15:18
  • It is not numbered but it the line in the second while loop in line 50, socket1.send(bytes('0', 'UTF-8')) at def get(commandName) – Jaiyeola May 27 '19 at 05:16
  • They were both using the same port 5000, I made a mistake while editing the code – Jaiyeola May 27 '19 at 05:20
  • Please how can i fix it @Vishal, it is grad project assignment. Tell me what i can do to fix it. – Jaiyeola May 27 '19 at 08:50
  • @finomnis, anyway i can find solution to it. it is my assignment and i am out of options – Jaiyeola May 27 '19 at 08:51
  • Apart of the port, it worked for me.... I'm not sure what the problem is. The lls and the FileDownload worked, so I'm not sure what your problem is. Again, try to reduce your code to a minimal example. – Finomnis May 27 '19 at 08:57
  • The problem is when I received the a file from the sever, it worked but when i requested to download another file from the server on the same socket, The client crash with brokenpipeerror. – Jaiyeola May 27 '19 at 09:05
  • Well, you see, THAT would have been a useful information to write in your question. I'm pretty sure you would have a solution by now. – Finomnis May 27 '19 at 09:05
  • Also, just a small issue, but don't write `#!/usr/bin/python3.7`, instead use `#!/usr/bin/env python3` – Finomnis May 27 '19 at 09:08
  • But I have no idea how to fix it, I tried using conn.close() to reset the connection but it still wasn't working. I don't know what to do now – Jaiyeola May 27 '19 at 09:20
  • @finomnis, Please what can I do I really need your help, I have tried everything I can. – Jaiyeola May 27 '19 at 10:21
  • @Jaiyeola as my first answer was deleted, I cannot answer again. Nonetheless, here is my answer: https://pastebin.com/qtsBVp8r – Finomnis May 27 '19 at 10:30
  • Feel free to post that pastebin content as response to your own question, I give you permission. – Finomnis May 27 '19 at 10:35
  • Okay! Thank you very much, I really appreciate this – Jaiyeola May 27 '19 at 10:42

1 Answers1

0

Server.py

class BufferedReceiver():
    def __init__(self, sock):
        self.sock = sock
        self.buffer = ""
        self.bufferPos = 0

    def _fetch(self):
        while self.bufferPos >= len(self.buffer):
            self.buffer = self.sock.recv(1024)
            # print(self.buffer)
            self.bufferPos = 0


    def take(self, amount):
        result = bytearray()
        while(len(result) < amount):
            # Fetch new data if necessary
            self._fetch()

            result.append(self.buffer[self.bufferPos])
            self.bufferPos += 1
        return bytes(result)

    def take_until(self, ch):
        result = bytearray()
        while True:
            # Fetch new data if necessary
            self._fetch()

            nextByte = self.buffer[self.bufferPos]
            self.bufferPos += 1

            result.append(nextByte)
            if bytes([nextByte]) == ch:
                break

        return bytes(result)

Then, I simplified your server send routine after the else::

        string = reqCommand.split(' ', 1)  # in case of 'put' and 'get' method
        if len(string) > 1:
            reqFile = string[1]

            if string[0] == 'FileDownload':
                with open(reqFile, 'rb') as file_to_send1:
                    # get the entire filesize, which sets the read sector to EOF
                    file_size = len(file_to_send1.read())
                    # reset the read file sector to the start of the file
                    file_to_send1.seek(0)
                    # pass the file size over to client in a small info chunk
                    print('Filesize:', file_size)
                    conn.send((str(file_size)+'\n').encode())
                    #send the total file size off the client
                    c = 0
                    while (c*bufsize) < file_size:
                        send_data = file_to_send1.read(bufsize)
                        conn.send(send_data)
                        c += 1
                print('Send Successful')

Client.py

def get(commandName):
    socket1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    socket1.connect((HOST, PORT))
    socket1.send(commandName.encode("utf-8"))

    receiver = BufferedReceiver(socket1)

    string = commandName.split(' ', 1)
    inputFile = string[1]

    # before starting to write new file, get file size
    file_size = int(receiver.take_until(b'\n').decode().strip()) # from file_to_send3
    print ('Filesize:', file_size)
    # set byte buffer size
    bufsize = 4096
    # this only opens the file, the while loop controls when to close
    with open(inputFile, 'wb+') as file_to_write:
        # while written bytes to out is less than file_size

        c = 0
        while True:

            # Compute how much bytes we have left to receive
            bytes_left = file_size - bufsize * c

            # If we are almost done, do the final iteration
            if bytes_left <= bufsize:
                file_to_write.write(receiver.take(bytes_left))
                break

            # Otherwise, just continue receiving
            file_to_write.write(receiver.take(bufsize))
            c += 1

    #TODO open file again, verify.
    # Generate MD5 on server while sending. Then, send MD5 to client.
    # Open finished file in client again and compare MD5s

    print('Download Successful')
    socket1.close()
    return
Jaiyeola
  • 17
  • 5