Advertisement
Guest User

Untitled

a guest
May 27th, 2019
176
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.85 KB | None | 0 0
  1. Problems I found:
  2.  
  3. - `c` does not need to be a global variable. Also, it never gets reset to 0 before transfer.
  4. - Why do you write the file size to a temp file, instead of just sending it to the client directly?
  5. - recv and send does not guarantee that the data does not get broken up. To guarantee that is your responsibility. I'd suggest you to write a wrapper class that receives repeatedly until you are done.
  6. - **NEVER** open a file simultaneously for writing and reading. File operations are delicate things. Write everything first, compute a checksum, then close the file and read it again, compare the checksums.
  7. - Learn to use the debugger. Get an IDE like pycharm, and step through your code, that will give you a better understanding of what exactly happens, and what you need to change.
  8. - You don't need a response from the client if everything is ok. This is already built into the TCP Protocol, as you are using SOCK_STREAM.
  9. - Don't `file.close()` files that you opened with `with open() as`.
  10. - The `break` in the server send data loop was indented wrong
  11. - Actually, no special case is needed for the server send loop final iteration
  12.  
  13. So, a little code for you. This fixes the problem that you cannot rely on the `recv` command to return *exactly* the amount of bytes you want. Also, this can do 'receive until we hit character':
  14.  
  15. ``` python
  16. class BufferedReceiver():
  17. def __init__(self, sock):
  18. self.sock = sock
  19. self.buffer = ""
  20. self.bufferPos = 0
  21.  
  22. def _fetch(self):
  23. while self.bufferPos >= len(self.buffer):
  24. self.buffer = self.sock.recv(1024)
  25. # print(self.buffer)
  26. self.bufferPos = 0
  27.  
  28.  
  29. def take(self, amount):
  30. result = bytearray()
  31. while(len(result) < amount):
  32. # Fetch new data if necessary
  33. self._fetch()
  34.  
  35. result.append(self.buffer[self.bufferPos])
  36. self.bufferPos += 1
  37. return bytes(result)
  38.  
  39. def take_until(self, ch):
  40. result = bytearray()
  41. while True:
  42. # Fetch new data if necessary
  43. self._fetch()
  44.  
  45. nextByte = self.buffer[self.bufferPos]
  46. self.bufferPos += 1
  47.  
  48. result.append(nextByte)
  49. if bytes([nextByte]) == ch:
  50. break
  51.  
  52. return bytes(result)
  53. ```
  54.  
  55. Then, I simplified your server send routine after the `else:`:
  56. ```python
  57. string = reqCommand.split(' ', 1) # in case of 'put' and 'get' method
  58. if len(string) > 1:
  59. reqFile = string[1]
  60.  
  61. if string[0] == 'FileDownload':
  62. with open(reqFile, 'rb') as file_to_send1:
  63. # get the entire filesize, which sets the read sector to EOF
  64. file_size = len(file_to_send1.read())
  65. # reset the read file sector to the start of the file
  66. file_to_send1.seek(0)
  67. # pass the file size over to client in a small info chunk
  68. print('Filesize:', file_size)
  69. conn.send((str(file_size)+'\n').encode())
  70. #send the total file size off the client
  71. c = 0
  72. while (c*bufsize) < file_size:
  73. send_data = file_to_send1.read(bufsize)
  74. conn.send(send_data)
  75. c += 1
  76. print('Send Successful')
  77. ```
  78.  
  79. Finally, here the client `get()`:
  80. ```python
  81. def get(commandName):
  82. socket1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  83. socket1.connect((HOST, PORT))
  84. socket1.send(commandName.encode("utf-8"))
  85.  
  86. receiver = BufferedReceiver(socket1)
  87.  
  88. string = commandName.split(' ', 1)
  89. inputFile = string[1]
  90.  
  91. # before starting to write new file, get file size
  92. file_size = int(receiver.take_until(b'\n').decode().strip()) # from file_to_send3
  93. print ('Filesize:', file_size)
  94. # set byte buffer size
  95. bufsize = 4096
  96. # this only opens the file, the while loop controls when to close
  97. with open(inputFile, 'wb+') as file_to_write:
  98. # while written bytes to out is less than file_size
  99.  
  100. c = 0
  101. while True:
  102.  
  103. # Compute how much bytes we have left to receive
  104. bytes_left = file_size - bufsize * c
  105.  
  106. # If we are almost done, do the final iteration
  107. if bytes_left <= bufsize:
  108. file_to_write.write(receiver.take(bytes_left))
  109. break
  110.  
  111. # Otherwise, just continue receiving
  112. file_to_write.write(receiver.take(bufsize))
  113. c += 1
  114.  
  115. #TODO open file again, verify.
  116. # Generate MD5 on server while sending. Then, send MD5 to client.
  117. # Open finished file in client again and compare MD5s
  118.  
  119. print('Download Successful')
  120. socket1.close()
  121. return
  122. ```
  123.  
  124. Hopefully this helps :)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement