код ошибки 1024 tftp сервера

Я пишу tftp-сервер на C и тестирую его с помощью команды tftp на терминале. Однако в большинстве случаев я получаю следующее, когда пытаюсь отправить RRQ:

tftp> get a.txt
sent RRQ <file=a.txt, mode=netascii>
received ERROR <code=4, msg=>
Error code 1024:

Другой случай, когда произошло:

tftp> get a.txt
sent RRQ <file=a.txt, mode=netascii>
received DATA <block=20334, 512 bytes>
discarded 4 packets

и этот: это может выглядеть правильно, но это почти не произошло. Текстовый файл, который я использую для проверки, имеет размер 857 байт.

sent ACK <block=1>
received DATA <block=1, 512 bytes>
sent ACK <block=1>
received DATA <block=2, 345 bytes>
Received 857 bytes in 0.0 seconds

и вот часть моего кода
Здесь буфер представляет собой массив символов размера 512, чтобы упростить код, я удалил часть кода обработки ошибок
Спасибо, кто может помочь

            #include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <cerrno>//define opcode for later use
enum opcode {
RRQ = 1,
WRQ,
DATA,
ACK,
ERROR
};void handle_write(struct sockaddr_in * sock_info, char* filename, int BUF_LEN){
//printf("Received write request + %d\n", WRQ);
return;
}

void handle_error(unsigned short int * opcode_ptr, char* buffer, socklen_t sockaddr_len, int server_socket, struct sockaddr_in * sock_info, const char* errormsg){
ssize_t n;
*opcode_ptr = htons(ERROR);
*(opcode_ptr + 1) = htons(1);
*(buffer + 4) = 0;
//memcpy(buffer+4, errormsg, strlen(errormsg));
intr_send:
n = sendto(server_socket, buffer, 5, 0,
(struct sockaddr *)sock_info, sockaddr_len);
if(n < 0) {
if(errno == EINTR) goto intr_send;
perror(errormsg);
exit(-1);
}
return;
}

int main() {
int BUF_LEN = 516;
ssize_t n;
char buffer[BUF_LEN];
socklen_t sockaddr_len;
int server_socket;
struct sigaction act;
unsigned short int opcode;
unsigned short int * opcode_ptr;
struct sockaddr_in sock_info;
memset(&sock_info, 0, sockaddr_len);

//----------setup the server----------------//
sock_info.sin_addr.s_addr = htonl(INADDR_ANY);
sock_info.sin_port = htons(5743);
sock_info.sin_family = PF_INET;

if((server_socket = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket");
exit(-1);
}

sockaddr_len = sizeof(sock_info);
if(bind(server_socket, (struct sockaddr *)&sock_info, sockaddr_len) < 0) {
perror("bind");
exit(-1);
}

getsockname(server_socket, (struct sockaddr *)&sock_info, &sockaddr_len);
printf("UDP server listening on port: %d\n", ntohs(sock_info.sin_port));
//----------setup the server----------------//

while(1){
intr_recv:
n = recvfrom(server_socket, buffer, BUF_LEN, 0, (struct sockaddr *)&sock_info, &sockaddr_len);

if(n < 0) {
if(errno == EINTR) goto intr_recv;
perror("recvfrom()");
exit(-1);
}
opcode_ptr = (unsigned short int *)buffer;
opcode = ntohs(*opcode_ptr);    //the opcode will be either RRQ or WRQ according to the test
if(opcode != RRQ && opcode != WRQ) {
/* Illegal TFTP Operation */
handle_error(opcode_ptr, buffer, sockaddr_len, server_socket, &sock_info, "invalid command");
}
else {
if(fork() == 0) {
/* Child - handle the request */
FILE* fd;
char* filename;
filename = strdup(buffer+2);  //this is the filename to be read (i.e. a.txt)

printf("request received\n");
char data[512];
//----------------------------------handle read request-------------------------------------//
if(opcode == RRQ){
int blocknumber = 0;
int i = 0; //counter for loop
fd = fopen(filename, "r");
free(filename);
//uint8_t data[512];
ssize_t datalen, n;
int done = 0;   //this is a boolean indicator that indicates whether the packet transfering process is done or not.
while(!done){
datalen = fread(data, 1, 512, fd);
blocknumber++;
if(datalen < 512){
done = 1;       //according to rfc 1350, the last packet will have a data length less than 512 bytes.
}
//for(i = 5; i > 0; i--){
*opcode_ptr = htons(DATA);
opcode = ntohs(*opcode_ptr);
*(opcode_ptr + 1) = htons(blocknumber);
memcpy(buffer + 4, data, datalen);
buffer[datalen + 4] = '\0';
//*(buffer + 4) = 0;
//printf("%d  %s\n", datalen, buffer+2);
n = sendto(server_socket, buffer, 4 + datalen, 0, (struct sockaddr *)&sock_info, sockaddr_len);
if(n < 0){
perror("sendto() failed");
exit(-1);
}
//printf("done %d\n", done);
//char buffer[512];
n = recvfrom(server_socket, buffer, sizeof(buffer), 0, (struct sockaddr *)&sock_info, &sockaddr_len);
opcode_ptr = (unsigned short int *)buffer;
opcode = ntohs(*opcode_ptr);
if(n >= 0 && n < 4){
//handle_error(opcode_ptr, buffer, sockaddr_len, server_socket, &sock_info, "invalid request size");
}
if(n > 4){
break;
}
//}
//if(i != 0){
//    printf("Transfer timeout!\n");
//    exit(1);
//}
//printf("opcode is %d\n", opcode);
if(opcode == ERROR){
printf("Error received\n");
exit(1);
}

if(opcode != ACK){
printf("Invalid message received\n");
exit(1);
}
}
}
//----------------------------------handle read request-------------------------------------////----------------------------------handle write request------------------------------------//

//----------------------------------handle write request------------------------------------//

close(server_socket);
break;
}
else {
/* Parent - continue to wait */
}
}
}

return EXIT_SUCCESS;
}

0

Решение

Я прочитал ваш код, но не проверен выполнением.

Сравнивая с RFC 1350, что я нашел

  • Поле данных занимает до 512 байт, поэтому 512 байт buffer недостаточно, потому что нет места для заголовка (код операции и блок #). Вам нужно как минимум еще 4 байта.
  • Вы пишете данные из buffer + 2 с помощью memcpy(), Это должно уничтожить номер блока. Похоже на то buffer + 4 следует использовать вместо
  • buffer[datalen + 2] = '\0'; не должно быть нужно Я думаю, что вы должны удалить его, потому что это уничтожит данные или вызовет переполнение буфера.
  • Вы должны закрыть файл, открытый после обработки запроса на чтение.
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]