Я пытаюсь передать данные размером около 100 МБ через сокет соединения TCP ipv4.
Я вычисляю контрольную сумму в клиенте перед отправкой, чтобы увидеть контрольную сумму.
После отправки файла данных на сервер, и сервер записывает его в новый файл, я снова вычисляю контрольную сумму и вижу другое.
Я думаю, вероятно, с моими функциями отправки и получения.
Функция Sender, используемая в CLIENT:
void send_file(FILE *fp, int sockfd) {
int n;
char data[SIZE] = {0};
while (fgets(data, SIZE, fp) != NULL) {
if (send(sockfd, data, sizeof(data), 0) == -1) {
perror("[-]Error in sending file.");
exit(1);
}
bzero(data, SIZE);
}
}
Функция Writer используется на СЕРВЕРЕ:
void write_file(int sockfd, char *filename) {
int n;
FILE *fp;
//char *filename = "new_data.txt";
char buffer[SIZE];
fp = fopen(filename, "w");
while (1) {
n = recv(sockfd, buffer, SIZE, 0);
if (n <= 0) {
break;
return;
}
fprintf(fp, "%s", buffer);
bzero(buffer, SIZE);
}
}
Ниже есть хороший совет. Но вам, вероятно, нужно вызывать fopen
с "rb"
и "wb"
в Windows, чтобы \r\n
не переводилось в текстовом потоке.
Вызов bzero() — это карго-культовая трата циклов, и, в любом случае, он не подходит для обнуления буфера при первом проходе. Вам не нужно рассматривать буфер cintent как строку, заканчивающуюся NUL, потому что вы знаете 'n'. Я видел этот код несколько раз, и все с одними и теми же проблемами. Скопируйте свой код из лучшего источника.
Примечание: очень жаль, что вы удалили свой вопрос о слишком медленных каналах. Как следствие, это единственный способ связаться с вами. 2 часа - не слишком большой срок, чтобы оставить вопрос поднятым. Я только что закончил ответ. Мое решение заняло 0,1 секунды для 100 МБ со скоростью 653 МБ/с. Вы можете «восстановить» свой вопрос, если вам все еще нужна помощь [или задать новый и ответить мне здесь, чтобы предупредить меня]
@CraigEstey Мне очень жаль, я думал, что это больше не актуально, если вы можете мне помочь, я буду признателен и учусь на этом stackoverflow.com/questions/74746348/…
fgets() и fprintf() используются для чтения и записи строк с завершающим нулем, а не произвольных двоичных данных. fread() и fwrite() здесь ваши друзья. Что-то вроде:
Клиент:
#define CHUNK_SIZE 1024
char buffer[CHUNK_SIZE];
while ((num_bytes = fread(buffer, 1, CHUNK_SIZE, fp)) > 0)
{
send(sockfd, buffer, num_bytes, 0);
}
Сервер:
// Same chunk size and buffer as above
while ((num_bytes = recv(sock, buffer, CHUNK_SIZE, 0)) > 0)
{
fwrite(buffer, 1, num_bytes, fp);
}
Технически fwrite() и send() могут записать меньше байтов, чем вы их просите, и вам действительно следует зацикливаться, пока все байты не будут записаны.
Вы также должны технически открывать свои файлы в режимах «rb» и «wb» для двоичных файлов.
Windows также нуждается в передаче режима "b"
. то есть "rb"
и "wb"
в вызове fopen
.
@pmacfarlane я перехожу на ваш код, и я меняю fopens на rb и wb и все еще другую контрольную сумму, но файл выглядит равным, я не знаю, в чем проблема
Размеры файлов совпадают? Как дела с контрольной суммой? В коде или с помощью внешнего инструмента, такого как sha256sum или md5sum?
Я использую функцию, которая вычисляет контрольную сумму файла, файлы выглядят одинакового размера и одинакового размера в байтах, например, на 100% равны, но, возможно, некоторые символы отсутствуют, я действительно не знаю, или функция контрольной суммы неверна .
Какую ОС вы используете? Если Linux, запустите md5sum и/или sha256sum для обоих файлов и посмотрите, совпадают ли они. Если они это сделают, в вашей функции есть ошибка. Что было бы отдельным вопросом :-D.
@pmacfarlane Я работаю на Windows WSL Ubuntu 22.04, я могу отредактировать этот пост и добавить функцию контрольной суммы.
Вы почти наверняка должны иметь sha256sum и md5sum в WSL. Если ничего другого, у вас должна быть программа под названием «cksum». Попробуйте и посмотрите. Я думаю, что ваш код контрольной суммы - это новый вопрос.
@pmacfarlane stackoverflow.com/questions/74709938/…
Вы должны использовать fread() и fwrite() вместо fgets() и fprintf(). И проверьте результат fread(), он сообщает вам, сколько байтов вы прочитали, поэтому вы должны отправлять только это количество байтов.