0

クライアントからの読み取り要求 (RRQ) のみを処理する単純な tftp サーバーを作成しました。問題は、サーバーがクライアントに DATA パケットを送信していないように見えることです。送信されたバイトの長さをデータ パケット サイズと照合して、サーバーが DATA パケットを送信していないことを確認しました。

注: Linux に付属する標準の tftp クライアントを使用します。

これが私がこれまでに書いたコードです...

#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;
}

前もって感謝します :)

4

1 に答える 1

1

オペコード チェックが正しくないようです。

試す:

bufindex++;
 opcode = *bufindex++;

また、なぜsendto. それはファイルのサイズであるべきではありませんか?ファイルの実際のサイズではなく、パケットバッファのサイズを渡しているだけです。

への変更 :

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

于 2015-04-14T12:49:27.390 に答える