网络编程 day3

 文件传输与下载

#include <head.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;
}

面试题整理

1.OSI七层网络体系结构

答:物数网传会表应(物理层-数据链路层-网络层-传输层-会话层-表示层-应用层)

2.分层的好处

答:(1)各层间独立,每一层不需要知道下一层如何实现,而仅仅只需要知道该层通过层间的接口所提供的服务

(2)稳定,灵活性好,只需层间接口关系不变,而这层以上或以下层不受影响

(3)易于实现和维护

(4)促进标准化工作:每一层功能及其所提供的服务都有了精确的说明

(5)结构上不可分割:各层采用最合适的技术来实现

3.TCP/IP四层网络体系结构

答:应用层-传输层-网际层-链路层

4.每一层中重要协议

答:应用层:HTTP 超文本传输协议;FTP 文件传输协议;TFTP 简单文件传输协议;SMTP简单邮件传输协议

传输层:TCP 传输控制协议; UDP 用户数据报协议

网络层:IP 网际互联协议;ICMP 互联网控制信息协议;IGMP 互联网组管理

链路层:ARP 地址解析协议;RARP 逆向地址解析协议

5.路由器工作在哪一层、交换机工作在哪一层

答:网际层、链路层

6.TCP和UDP的区别

答:(1)TCP稳定可靠,面向连接,连接时有三次握手,断开时有四次握手;UDP不稳定不可靠,面向无连接,不会产生握手

(2)TCP数据传输效率低,耗费资源多;UDP数据传输效率高,实时性高

(3)TCP收发不同步,为提高效率,会有粘包现象;UDP收发同步,不会粘包

(4)TCP适用质量较高传输场景;UDP适用小尺寸的收数据给出应答较困难的情况

7.TCP服务器端实现

答:(1)创建套接字

(2)bind绑定端口号跟IP地址

(3)listen设置监听

(4)accept阻塞客户端连接请求

(5)数据收发函数:send、recv

(6)关闭套接字

  • 14
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心若向阳,何惧悲伤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值