TFTP 简介、通信过程
TFTP 概述
TFTP : 简单文件传送协议
最初用于引导无盘系统,用来传输小文件
特点:
基于UDP协议实现
不进行用户有效性认证
数据传输模式:
octet:二进制模式
netascii:文本模式
mail:已经不再支持
TFTP 通信过程
TFTP 通信过程总结
- 服务器在69端口等待客户端的请求
- 服务器同意,就使用临时端口与客户端通信
- 每个数据包的编号都会变化(从1开始)
- 每个数据包都要ACK的确认,如果超时,就会重新发送最后的包
- 数据的长度以512byte传输
- 小于512byte的数据意味着传输结束
TFTP 协议分析
注意:
以上的 0 代表的是'\0'
不同的差错码对应不同的错误信息
错误码:
- 0 Undefined 未定义
- 1 File not found 找不到文件
- 2 access violation 访问冲突
- 3 disk full or allocation exceeded 磁盘已满或超过分配
- 4 illegal TFTP operation 非法的TFTP操作
- 5 unknown transfer ID 未知的传输ID
- 6 file already exists 文件已经存在
- 7 no such user 没有这样的用户
- 8 unsupported option requested 不支持的选项请求
TFTP 带选项
读写请求中修改了选项
如果发送带选项的读写请求
tsize 选项
当读操作,tsize 选项参数必须为 0 ,服务器会返回待读取的文件大小
当写操作,tsize 选项参数为待写入的文件大小,服务器会显示该参数
blksize 选项
修改传输文件时使用的数据块大小(范围:8 ~ 65464)
timeout 选项
修改默认的数据传输超时时间(单位:秒)
TFTP通信过程总结(带选项)
- 可以通过发送 带选项的读/写请求 发送给server
- 如果server同意修改选项,就发送选项修改确认包
- server发送的数据,选项修改确认包都是临时port
- server 通过timeout来对丢失数据包的重新发送
练习—TFTP 客户端
要求:
使用TFTP协议,下载server上的文件到本地
实现思路:
- 构造请求报文,送到服务器(69端口)
- 等待服务器回应
- 分析服务器回应
- 接受数据,直到接收到的数据包小于规定数据包大小
UDP 广播
广播:由一台主机向该主机所在子网内所有主机发送数据方式
广播只能用于UDP或原始IP实现,不能用TCP
广播的用途
单个服务器与多个客户主机通信时减少分组流通
以下协议用到广播
- 地址解析协议(ARP)
- 动态主机配置协议(DHCP)
- 网络时间协议(NTP)
UDP广播的特点
- 处在同一子网的所有主机都必须处理数据
- UDP数据包会沿协议栈上一直到UPD层
- 运行音视频等高速率工作的应用,会带来大负
- 局限于局域网内使用
UDP广播地址
{网络ID,主机ID}
网络ID 表示 由子网掩码中 1 覆盖的连续位
主机ID 表示 由子网掩码中 0 覆盖的连续位
定向广播地址:主机ID全 1
- 192.168.220.0/24,其定向广播地址为 192.168.220.255
- 通常路由器不转发该广播
受限广播地址:255.255.255.255
路由器从不转发该广播
广播与单播的对比
单播
广播
套接口选项
/*
成功: 执行返回 0
失败: 返回-1
*/
int setsockopt(int sockfd, int level, int optname, const viod *optval, socklen_t optlen);
广播示例
int main(int argc, char *argc[])
{
int sock_fd = 0;
char buff[1024] = "";
unsigned short port = 8000;
struct sockaddr_in send_addr;
bzero(&send_addr, sizeof(send_addr));
send_addr.sin_family = AF_INET;
send_addr.sin_port = htons(port);
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
if(sock_fd < 0)
{
perror("socket failed");
close(sock_fd);
exit(1);
}
if(argc > 1)
{
send_addr.sin_addr.s_addr = inet_addr(argv[1]);
}
else
{
printf("not have a server IP");
exit(1);
}
int yes = 1;
setsockopt(sock_fd, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes));
strcpy(buf, "boardcast sucess");
int len = sendto(sock_fd,
buff,
strlen(buff),
0,
(struct sockaddr *)&send_addr,
sizeof(send_addr));
if(len < 0)
{
printf("send error \n");
close(sock_fd);
exit(1);
}
return 0;
}
UDP 多播
多播概述
多播:
数据的收发仅仅在同一个分组中进行
多播的特点:
- 多播地址标识一组接口
- 多播可以用于广域网使用
- 在ipv4中,多播是可选的
多播地址
IPv4 的 D 类地址是多播地址
十进制:224.0.0.1 239.255.255.254
十六进制:E0.00.00.01 EF.FF.FF.FE
多播地址向以太网 MAC 地址的映射
UDP 多播工作过程
多播地址结构体
在 IPv4 因特网域(AF_INET)中,多播地址结构体用如下结构体 ip_mreq 表示
struct in_addr
{
in_addr_t s_addr;
};
struct ip_mreq
{
struct in_addr imr_multiaddr; //多播组IP
struct in_addr imr_interface; //将要添加到多播组的IP
};
多播套接口选项
/*
成功: 执行返回 0
失败: 返回-1
*/
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
加入多播组示例
char group[INET_ADDRSTRLEN] = "244.0.1.1";
struct ip_mreq mreq; //定义一个多播组地址
mreq.imr_multiaddr.s_addr = inet_addr(group); //添加一个多播组IP
mreq.imr_interface.s_addr = htonl(INADDR_ANY); //添加一个将要添加到多播组的IP
setsockopt(sockfd, IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));