Bootstrap

3、UDP中TFTP协议应用

一、tftp协议

TFTP(Trivial File Transfer Protocol,简单文件传输协议)是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂、开销不大的文件传输服务。端口号为69。

TFTP服务的端口号--69

TFTP:简单文件传送协议

最初用于引导无盘系统,被设计用来传输小文件

TFTP特点:

基于 UDP 协议实现

不进行用户有效性认证

数据传输模式:

octet:二进制模式

netascii:文本模式

mail:已经不再支持

TFTP通信流程:

客户端---用户

服务器--TFTP服务

协议内容:

读操作:

0x00 0x01 +文件名字+'\0'+"netascii"+'\0';

写操作:

0x00 0x02 +文件名字+'\0'+"netascii"+'\0';

数据包:

0x00 0x03 +块编号(2字节)+有效数据(512字节)

应答信号:

0x00 0x04 +块编号(2字节)

TFTP服务器端的设置:

man手册内容分布:

第一章节---shell编程

第二章节--系统调用

第三章节--C语言标准库

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>




//./a.out 192.168.17.2 tftptest.txt
int main(int argv,char *argc[])
{

    //TFTP端口69
    int sock_fd=0;
    char send_buf[516]="";
    char rev_buf[600]="";
    struct sockaddr_in     ser_addr; 
    struct sockaddr_in     serv_addr; 
    int file_fd=0;
    if(argv<3)
    {
        perror("input data error");
        exit(-1);
    }
    //创建套接字
    sock_fd=socket(AF_INET,SOCK_DGRAM,0);

        //发送数据--读写数据帧
        // 0x00+0x01+文件名+'\0'+模式+'\0'
        ser_addr.sin_family=AF_INET;
        ser_addr.sin_port=htons(69);
        ser_addr.sin_addr.s_addr=inet_addr(argc[1]);//等同于inet_pton,但是没有inet_pton函数详细
       int send_len  =sprintf(send_buf,"%c%c%s%c%s%c",0x00,0x01,argc[2],0x00,"octet",0x00);

    sendto(sock_fd,send_buf,send_len,0,(struct sockaddr *)&ser_addr,sizeof(ser_addr));
    while(1)
    {
        int len=sizeof(serv_addr);

        int rev_len=  recvfrom(sock_fd,rev_buf,600,0,(struct sockaddr *)&serv_addr,&len);
        if(rev_buf[1]==0x03)
        {
        file_fd=  open(argc[2],O_CREAT|O_WRONLY,0666);
        if(file_fd<0)
        {
            perror("open:");
            exit(-1);
        }
      write(file_fd,rev_buf+4,rev_len-4);
    rev_buf[1]=0x04;
     sendto(sock_fd,rev_buf,4,0,(struct sockaddr *)&ser_addr,sizeof(ser_addr));

    }
    else if(rev_buf[1]==0x05)
    {
        printf("错误码--》0x%x\n",rev_buf[3]);
        printf("错误信息:%s\n",(rev_buf+4));
    }

      if(rev_len<516)
     {
        break;
     }
    close(file_fd);
    close(sock_fd);
    }









return 0;
}

二、UDP中的广播

广播:由一台主机向该主机所在子网内的所有主机发送数据的方式广播只能用 UDP 或原始 IP 实现,不能用 TCP。

UDP中的广播的作用

单个服务器与多个客户主机通信时减少分组流通

以下几个协议都用到广播

1、地址解析协议(ARP)

2、动态主机配置协议(DHCP)

3、网络时间协议(NTP)

UDP的特性:

UDP广播中IP地址格式

{网络 ID,主机 ID}

192. 168 .2 .17

网络 ID 表示由子网掩码中 1 覆盖的连续位

主机 ID 表示由子网掩码中 0 覆盖的连续位

定向广播地址: 主机 ID 全 1

1、例:对于 192.168.220.0/24,其定向广播地址为 192.168.220.255

2、通常路由器不转发该广播

受限广播地址: 255.255.255.255

路由器从不转发该广播

单播的传输流程:

广播的传输流程:

套接字属性设置函数:

int setsockopt(int sockfd , int level, int optname, void *optval, socklen_t *optlen);

函数功能:设置套接字描述符的属性。

参数:
sockfd:要设置的套接字描述符。
level:选项定义的层次。或为特定协议的代码(如IPv4,IPv6,TCP,SCTP),或为通用套接字代码(SOL_SOCKET)。
optname:选项名。level对应的选项,一个level对应多个选项,不同选项对应不同功能。
optval:指向某个变量的指针,该变量是要设置新值的缓冲区。可以是一个结构体,也可以是普通变量
optlen:optval的长度。
返回值:
成功时返回0,失败时返回-1。

等级设置以及optname:

当level为SOL_SOCKET时,optname可以有以下选项(一部分)
SO_BROADCAST     允许发送广播数据            int
SO_DEBUG        允许调试                int
SO_LINGER        延迟关闭连接          struct linger
SO_OOBINLINE      带外数据放入正常数据流         int
SO_RCVBUF        接收缓冲区大小             int
SO_SNDBUF        发送缓冲区大小             int
SO_RCVLOWAT      接收缓冲区下限             int
SO_SNDLOWAT      发送缓冲区下限             int
SO_RCVTIMEO       接收超时           struct timeval
SO_SNDTIMEO       发送超时           struct timeval

当level为IPPROTO_IP时,optname可以有以下选项(一部分)
IP_HDRINCL       在数据包中包含IP首部          int
IP_OPTINOS       IP首部选项               int
IP_TTL         生存时间                int

当level为IPPRO_TCP时,optname可以有以下选项(一部分)
TCP_MAXSEG       TCP最大数据段的大小          int
TCP_NODELAY       不使用Nagle算法             int

三、多播通信:

将同一个网络中的设备进行分组,以实现不同的数据传输的需求

多播地址设置:

IPv4 的 D 类地址是多播地址

十进制: 224.0.0.1 --239.255.255.254

十六进制: E0.00.00.01 EF.FF.FF.FE

多播地址向以太网 MAC 地址的映射

多播地址结构体

INADDR_ANY--->当前主机下任意IP地址

;