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;
}
相关推荐
brrdg_sefg1 小时前
WEB 漏洞 - 文件包含漏洞深度解析
前端·网络·安全
Quz5 小时前
Wireshark协议相关功能:过滤、启用/禁用、导出和统计查看
网络·测试工具·wireshark
安全方案6 小时前
如何增强网络安全意识?(附培训PPT资料)
网络·安全·web安全
tjjingpan7 小时前
HCIA-Access V2.5_6_3_GPON关键技术
网络
yuanbenshidiaos7 小时前
数据结构----链表头插中插尾插
网络·数据结构·链表
洛神灬殇7 小时前
彻底认识和理解探索分布式网络编程中的SSL安全通信机制
网络·分布式·ssl
总是学不会.7 小时前
第五篇:前后端如何“扯皮”——HTTP 在开发中的应用
java·网络·网络协议·http·开发
网络安全(king)7 小时前
网络安全设备
网络·web安全·php
叫我菜菜就好7 小时前
【Flutter_Web】Flutter编译Web第三篇(网络请求篇):dio如何改造方法,变成web之后数据如何处理
前端·网络·flutter