2015-04-14 2 views
0

Я написал простой сервер tftp, который обрабатывает запросы на чтение (RRQ) от клиентов. Проблема в том, что сервер, похоже, не отправляет DATA-пакеты клиенту. Я убедился, что сервер не отправляет пакет DATA, проверяя длину отправленных байтов на размер пакета данных.TFTP-сервер не отправляет пакеты DATA

Примечание: Я использую стандартный клиент tftp, который поставляется с Linux.

Вот код, который я написал до сих пор ...

#include <stdio.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <stdlib.h> 
#include <string.h> 
#include <errno.h> 

void sendFile (char *Filename, char *mode, struct sockaddr_in client) 
{ 
    char path[70] = "tmp/"; 
    char filebuf [1024]; 
    int acked = 0; // Number of acked data portions 
    int count = 0; // Number of data portions we sent 
    unsigned char packetbuf[1024]; 
    char recvbuf[1024]; 
    socklen_t recv_size; 

    int sock = socket(PF_INET, SOCK_DGRAM, 0); 

    FILE *fp; 
    char fullpath[200]; 
    strcpy(fullpath, path); 
    strncat(fullpath, Filename, sizeof(fullpath) -1); 
    fp = fopen(fullpath, "r"); 
    if (fp == NULL) 
     perror(""); 

    memset(filebuf, 0, sizeof(filebuf)); 
    while (1) 
    { 
     int ssize = fread(filebuf, 1 , 512, fp); 
     count++;   
     sprintf((char *) packetbuf, "%c%c%c%c", 0x00, 0x03, 0x00, 0x00); 
     memcpy((char *) packetbuf + 4, filebuf, ssize); 
     packetbuf[2] = (count & 0xFF00) >> 8; 
     packetbuf[3] = (count & 0x00FF); 

     int len = 4 + ssize;   

     if (sendto(sock, packetbuf, len, 0, (struct sockaddr *) &client, sizeof(client)) != len) 
      puts("SENDING FAILED!"); 

     memset(recvbuf, 0, 1024); 
     recvfrom(sock, recvbuf, 1024, 0, (struct sockaddr *) &client, &recv_size); 
     if (recvbuf[1] == 4) 
      puts("Acked"); 

     if (ssize != 512) 
      break; 
    } 
} 


int main() 
{ 
    int udpSocket, nBytes; 
    char buffer[1024], filename[200], mode[20], *bufindex, opcode; 
    struct sockaddr_in serverAddr, client; 
    struct sockaddr_storage serverStorage; 
    socklen_t addr_size; 

    udpSocket = socket(AF_INET, SOCK_DGRAM, 0); 

    serverAddr.sin_family = AF_INET; 
    serverAddr.sin_port = htons(69); 
    serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 
    memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero); 

    bind(udpSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr)); 
    memset(buffer,0,1024); 

    while(1) 
    { 
     nBytes = recvfrom(udpSocket,buffer,1024,0,(struct sockaddr *)&client, &addr_size); 

     bufindex = buffer; 
     bufindex++; 

     // Extracting the opcode from the packet...  
     opcode = *bufindex++; 

     // Extracting the filename from the packet... 
     strncpy(filename, bufindex, sizeof(filename)-1); 

     bufindex += strlen(filename) + 1; 

     // Extracting the mode from the packet...  
     strncpy(mode, bufindex, sizeof(mode)-1); 

     // If we received an RRQ... 
     if (opcode == 1) 
      sendFile(filename, mode, client); 
    } 
    return 0; 
} 

Заранее спасибо :)

+0

ли вы проверить трассировку пакетов б/ш сервер и клиент? Выходит ли файл с сервера? – Prabhu

+0

@Prabhu Я только что проверил трассировку пакетов, и кажется, что файл не выходит из сервера. – user3490561

+0

@Prabhu Я также проверил сокет в 'sendFile()' и, похоже, он был создан успешно. – user3490561

ответ

1

Ваш чек опкод кажется неверным.

Try:

bufindex++; 
opcode = *bufindex++; 

Кроме того, почему 1024 байт sendto. Разве это не размер файла? Вы просто передаете размер пакета buf вместо фактического размера файла.

Изменить на:

sendto((sock, packetbuf, len, 0, (struct sockaddr *) &client, sizeof (client)));

+0

Правильный человек, спасибо. Я изменил код выше, и теперь у меня другая проблема. 'Sendto' в' sendfile' всегда не удается отправить. – user3490561

+0

проверьте мой комментарий – user3490561

+0

@ user3490561 Если вы нашли ответ полезным, можете ли вы поддержать и принять ответ? – Prabhu

Смежные вопросы