2024.1.16 网络编程 作业

思维导图

练习题

1.基于UDP的TFTP文件传输,实现文件下载上传

cpp 复制代码
#include <myhead.h>

int main(int argc, char const *argv[])
{
    // 创建套接字UDP通信
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (-1 == sockfd)
    {
        perror("socket error");
        return -1;
    }
    // 填充服务器网络信息结构体
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;
    //端口号填69
    sin.sin_port = htons(69);
    //填写windows ip地址
    sin.sin_addr.s_addr = inet_addr("192.168.124.19");
    //结构体长度
    socklen_t socklen = sizeof(sin);

    //数据包数据的长度以512字节传输
    char buffer[516] = {0};
    //返回的ACK
    char ack[4];
    //操作码
    short code = 0;
    //块编号 or 错误码
    short BlockoErr = 0;
    //数据的长度以512Byte传输
    char text[512] = {0}; //文件内容 或 错误信息
    //校验收到的块编号
    int N = 0;
    //返回的文件描述符
    int fd;
    int ret = 0;

    //输入文件名
    char filename[64] = {0};
    printf("下载文件名: ");
    scanf("%s", filename);

    //使用 sprintf 组包
    //返回成功格式化字符的个数
    ret = sprintf(buffer, "%c%c%s%c%s%c", 0, 1, filename, 0, "octet", 0);

    //首次发送请求
    if (-1 == sendto(sockfd, buffer, ret, 0, (struct sockaddr *)&sin, socklen))
    {
        perror("sendto error");
        return -1;
    }
    //循环接收服务器发来的数据包
    while (1)
    {
        //因为有临时端口需要保存服务器的网络信息结构体
        ret = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&sin, &socklen);
        if (-1 == ret)
        {
            perror("recvfrom error");
            return -1;
        }

        //解析操作码
        code = ntohs(*(short *)buffer);
        //解析块编号or错误码
        BlockoErr = ntohs(*(short *)(buffer + 2));
        //解析文件内容or错误信息,并将内容放入数据段
        strncpy(text, buffer + 4, sizeof(text));
        //解析数据包中的内容
        if (3 == code && BlockoErr == N + 1)
        {
            //校验块编号+1
            N++;
            //要接收的数据包
            //如果是第一次接到数据包 要创建文件
            if (BlockoErr == 1)
            {
                fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0664);
                if (-1 == fd)
                {
                    perror("open error");
                }
            }
            //将文件内容写入文件 ret是buffer中去掉前4字节操作数和块编号所剩余的内容
            if (-1 == write(fd, text, ret - 4))
            {
                perror("write error");
            }
            // 组装ACK
            *(short *)ack = htons(4);
            *(short *)(ack + 2) = htons(BlockoErr);
            //回复ACK包
            if (-1 == sendto(sockfd, ack, 4, 0, (struct sockaddr *)&sin, socklen))
            {
                perror("recvfrom error");
            }
            //文件接收完毕
            if (ret < 512)
                break;
        }
    }

    printf("文件[%s]下载完成\n", filename);
    close(sockfd);
    return 0;
}
相关推荐
andxe14 小时前
安科士AndXe 400G QSFP-DD LR8光模块芯片架构与品控体系解析
网络·光模块·光通信
去码头整点薯条9815 小时前
网络实验报告10
网络
坚定的共产主义生产设备永不宕机15 小时前
路由协议OSPF进阶一篇讲全
网络
碎碎念_49216 小时前
以太网技术、VLAN、STP详解
网络·stp·vlan
hbugs00117 小时前
【案例分享】全网首个华三数据中心流量可视化实验,基于EVE-NG V7平台
网络·网络协议·安全·devops·eve-ng
不会C语言的男孩18 小时前
第 13 章 网络与分布式系统基础
网络
山东穆柯传感器18 小时前
安全触边损坏如何维修及更换配件
网络·安全
huainingning18 小时前
华三ACL单向TCP互通组网-通过Established状态回包实现
运维·网络·tcp/ip
Johnstons18 小时前
游戏网络测试怎么做?从延迟到丢包,一套完整的游戏弱网测试方案
网络·游戏·php
Rocket-Luo19 小时前
谈谈企业中的网络安全
网络·安全·web安全