简单的TFTP客户端


int main(int argc, char const *argv[])
{
    if (argc < 4)
    {
        printf("请输入IP地址与端口号,格式:%s 192.168.31.1 8888\n [filename]", argv[0]);
        return 1;
    }

    FILE *file = 0;
    int clinet = socket(AF_INET, SOCK_DGRAM, 0);
    struct sockaddr_in addr = {0};
    addr.sin_family = AF_INET;
    addr.sin_port = htons(atoi(argv[2]));
    addr.sin_addr.s_addr = inet_addr(argv[1]);
    socklen_t length = sizeof(addr);
    char buf[516] = {0}; // 最大使用
    char filename[512] = {0};
    int ret = 0;
    unsigned short used = 0;
    // 要求用户输入请求
    if (argc == 4) // 外界输入了文件名
    {
        strcpy(filename, argv[3]);
    }
    else
    {
        printf("请输入文件名\n");
        scanf(" %s", filename);
    }
    unsigned short filenamelen = 0;
    filenamelen = strlen(filename);
    *(unsigned short *)buf = ntohs(1);
    memcpy(2 + buf, filename, filenamelen);
    memcpy(filenamelen + 2 + buf, "\0octet\0", 7);
    unsigned short int blockNum = 0;
    ret = sendto(clinet, buf, filenamelen + 2 + 7, 0, &addr, sizeof(addr));

    addr.sin_addr.s_addr = 0;
    addr.sin_port = 0;
    do
    {
        ret = recvfrom(clinet, buf, sizeof(buf), 0, &addr, &length);
        // printf("ret=%d\n",ret);
        used = 0;
        switch (used += 2, ntohs(*(unsigned short int *)buf))
        {
        case 3:
            // 这里需要判断ret的值
            blockNum = ntohs(*(unsigned short int *)(buf + used));
            used += 2;
            printf("%d block received\n", blockNum);
            if (!file)
            {
                file = fopen(filename, "w");
            }
            fseek(file, (blockNum-1) * 512, SEEK_SET);//block 从1开始计数,但文件指针从0开始
            fwrite(buf + used, ret-4, 1, file);
            *(unsigned short *)buf = ntohs(4);
            sendto(clinet, buf, 4, 0, (struct sockaddr *)&addr, sizeof(addr));
            break;

        case 4:
        case 1:
        case 2:
        case 5:
        default:
            printf("reveive error:\n opcode:%dblockCode:%d\n",
                   ntohs(*(unsigned short int *)buf), ntohs(*(unsigned short int *)buf + 2));
            exit(EXIT_FAILURE);
            break;
        }
    } while (ret == 516);//应该是>=516,但是数据包大小只有516
    fflush(file);
    fclose(file);
    return 0;
}

你可能感兴趣的:(linux)