Отправка «плавающих» данных через сокет

#sockets #python-3.x #tcp

#сокеты #python-3.x #tcp

Вопрос:

Клиент отправляет имя файла на сервер. Сервер сканирует файловую систему для всех экземпляров файла и заполняет словарь ключами в качестве абсолютных путей и значениями в качестве размеров файлов.

Написанный мной код кажется логически правильным, но иногда выполняется успешно, а иногда выдает ошибку.

Сервер

 import socket;
import sys;
import os;

serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM);
host = socket.gethostname();
port = 49000;
serverSocket.bind((host, port));
serverSocket.listen(1);

while True:
  connectionSocket, address = serverSocket.accept();
  fileName = connectionSocket.recv(1024).decode();

  dictionary = {};

  for path, dirs, files in os.walk(os.path.abspath(os.sep)):
    for f in files:
      if f == fileName:
        dictionary[os.path.join(path, f)] = os.stat(f).st_size / 1024;

  if len(dictionary) == 0:
    connectionSocket.send(('0').encode());
    print();
    print('File not found!');
    sys.exit();
  else:
    connectionSocket.send(('1').encode());

  connectionSocket.send(str(len(dictionary)).encode());
  for key, value in dictionary.items():
    connectionSocket.send(key.encode('utf-16'));
    # If i don't write following line, error vanishes
    connectionSocket.send(str(value).encode('utf-16'));

  # File transfer
  f = open(fileName, 'rb');
  byte = f.read(1024);
  while (byte):
    #print('Sending...');
    connectionSocket.send(byte);
    byte = f.read(1024);
  f.close();
  print();
  print('Done sending.');
  connectionSocket.close();
  break;
 

Клиент

 import socket;
import sys;
import os;

if len(sys.argv) != 2:
  print();
  print('Invalid arguments!');
  sys.exit();

clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM);
host = socket.gethostname();
port = 49000;
clientSocket.connect((host, port));
clientSocket.send((sys.argv[1]).encode());

if clientSocket.recv(1024).decode() == '0':
  print();
  print('File not found!');
  sys.exit();

dictionary_size = int(clientSocket.recv(1024).decode());
for i in range(dictionary_size):
  print();
  print(clientSocket.recv(1024).decode('utf-16'));
  # If I don't write this line, error vanishes
  print(float(clientSocket.recv(1024).decode('utf-16')));

# File Transfer
byte = clientSocket.recv(1024);
f = open('Received_'   sys.argv[1], 'wb');
while (byte):
  #print ('Receiving...');
  f.write(byte);
  byte = clientSocket.recv(1024);
f.close();
print();
print('Done receiving.');
clientSocket.shutdown(socket.SHUT_WR);
clientSocket.close();
 

Комментарии:

1. TCP — это поток. Первый вызов recv может использовать или не использовать полные данные, отправленные другой стороной. Решение, вероятно, будет включать что-то вроде значения start, stop и seperator между фактическими значениями. Затем ваш принимающий код может восстанавливаться до получения конечного символа

2. Когда это не работает, в чем ошибка? Пожалуйста, предоставьте полную обратную трассировку, если это возможно. Пара комментариев: 1) Python не является C / C , поэтому вам не нужно завершать каждое утверждение с помощью a ; . 2) Вы не отправляете размер файла, выражение os.stat(f).st_size / 1024 вычисляет только целое количество блоков 1K, но усечение из-за целочисленного деления не учитывает какой-либо конечный частичный блок.

3. Какую ошибку вы видите?

4. Ошибка: i.imgur.com/fW1FscL.png

5. @martineau Вы сказали, что os.stat(f).st_size / 1024 дает целое число, но когда я его печатаю (), оно дает правильный размер с плавающим значением. Недавно я начал использовать Python. ‘;’ — старая привычка. Это плохая практика?