[米联客-安路飞龙DR1-FPSOC] UDP通信篇连载-04 IP层程序设计

news2024/9/21 11:08:35

软件版本:Anlogic -TD5.9.1-DR1_ES1.1

操作系统:WIN10 64bit

硬件平台:适用安路(Anlogic)FPGA

实验平台:米联客-MLK-L1-CZ06-DR1M90G开发板

板卡获取平台:https://milianke.tmall.com/

登录“米联客”FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!

3.3 IP层

ICMP层数据和UDP层数据都要经过IP层打包或者解包,IP层主要功能为判断数据报文类型,进行IP首部校验,添加包头或者过滤包头,处理ICMP请求。

3.3.1 IP接收模块

该模块的主要功能是接收uiip_arp_rx传入的数据包,通过首部校验判断包头的正确性,对包头进行过滤,并且提取出UDP报文和ICMP报文。

该模块的状态机转换图如图所示。

WAIT_IP_PACKET:等待接收IP包,若I_ip_rvalid拉高,代表数据传入,进入RECORD_IP_HEADER状态。

RECORD_IP_HEADER:接收包头信息,20字节的包头数据全部接收完时,判断收到的IP地址和本地IP地址是否匹配,若不匹配,丢弃该帧,进入WAIT_PACKET_END状态;若匹配,则判断数据包类型。如果收到的数据报文为UDP数据报文,进入OUTPUT_UDP_PACKET状态。如果收到的数据报文为ICMP报文,则将数据传入ICMP子层模块,等待一包数据传输完成后,进入WAIT_PACKET_END状态。

OUTPUT_UDP_PACKET:将有效数据打拍后传输至UDP层,一包数据传输完成后,回到WAIT_IP_PACKET状态。

WAIT_PACKET_END:等待数据有效信号拉低,一帧数据传输完成,回到WAIT_IP_PACKET状态。

always@(posedge I_ip_clk or posedge I_reset) begin
    if(I_reset) begin
        cnt                     <= 5'd0;
        ip_version              <= 4'd0;    //IP首部-版本:4位数据表示IP版本号,为4时表示IPv4,为6时表示IPv6,IPv4使用较多。
        ip_header_len           <= 4'd0;    //IP首部-首部长度:4位数据表示IP首部一共有多少个32位(4个字节)数据。没有可选字段的IP首部长度为20个字节,故首部长度为5
        ip_tos                  <= 8'd0;    //IP首部-服务类型:8位服务类型被划分成两个子字段:3位优先级字段和4位TOS字段,最后一位固定为0。服务类型为0时表示一般服务。
        ip_pkg_len              <= 16'd0;   //IP首部-总长度:16位IP数据报总长度包括IP首部和IP数据部分,以字节为单位。利用IP首部长度和IP数据报总长度可以计算出IP数据报中数据内容的起始位置和长度
        ip_packet_id            <= 16'd0;   //IP首部-ID:16位标识字段,用来标识主机发送的每一份数据报。每发送一份报文它的值就会加1
        ip_packet_flag          <= 3'd0;    //IP首部-标志字段:3位标志字段的第1位是保留位,第2位表示禁止分片(1表示不分片,0允许分片),第3位标识更多分片,通常为010不分片
        ip_fragment_offset      <= 13'd0;   //IP首部-片偏移:13位片偏移,在接收方进行数据报重组时用来标识分片的顺序。
        ip_packet_ttl           <= 8'd0;    //IP首部-生存时间:    8位生存时间防止丢失的数据包在无休止的传播,一般被设置为64或者128
        ip_packet_protocol      <= 8'd0;    //IP首部-协议:8位协议类型表示此数据报所携带上层数据使用的协议类型,ICMP为1,TCP为6,UDP为17
        ip_header_checksum      <= 16'd0;   //IP首部-首部校验和:16位首部校验和,该字段只校验数据报的首部,不包含数据部分
        ip_src_address          <= 32'd0;   //IP首部-源IP地址:32位发送端的IP地址
        ip_dst_address          <= 32'd0;   //IP首部-目的IP地址:32位接收端的IP地址
        icmp_pkg_valid          <= 1'b0;    //icmp数据报文有效信号
        O_udp_ip_rvalid         <= 1'b0;    //UDP数据包有效
        O_udp_ip_rdata          <= 8'd0;    //UDP数据包有效输出
        STATE                   <= WAIT_IP_PACKET;
    end
    else begin
        case(STATE)
            WAIT_IP_PACKET:begin
                if(I_ip_rvalid) begin
                    ip_version          <=  I_ip_rdata[7:4];    //IP首部-版本:4位数据表示IP版本号
                    ip_header_len       <=  I_ip_rdata[3:0];    //IP首部-首部长度:4位数据表示IP首部一共有多少个32位(4个字节)数据
                    STATE               <=  RECORD_IP_HEADER;   //下一状态,继续接收IP头部信息
                end
                else
                    STATE               <=  WAIT_IP_PACKET;
            end
            RECORD_IP_HEADER:begin
                case(cnt)
                    0:  begin   ip_tos                      <=  I_ip_rdata; cnt <=  cnt + 1'b1;end  //IP首部-服务类型:8位服务类型被划分成两个子字段:3位优先级字段和4位TOS字段,最后一位固定为0。服务类型为0时表示一般服务。
                    1:  begin   ip_pkg_len[15:8]            <=  I_ip_rdata; cnt <=  cnt + 1'b1;end  //IP首部-总长度:16位IP数据报总长度包括IP首部和IP数据部分,以字节为单位。
                    2:  begin   ip_pkg_len[7:0]             <=  I_ip_rdata; cnt <=  cnt + 1'b1;end  //IP首部-总长度:16位IP数据报总长度包括IP首部和IP数据部分,以字节为单位。
                    3:  begin   ip_packet_id[15:8]          <=  I_ip_rdata; cnt <=  cnt + 1'b1;end  //IP首部-ID:16位标识字段,用来标识主机发送的每一份数据报。
                    4:  begin   ip_packet_id[7:0]           <=  I_ip_rdata; cnt <=  cnt + 1'b1;end  //IP首部-ID:16位标识字段,用来标识主机发送的每一份数据报。
                    5:  begin   
                        ip_packet_flag                      <=  I_ip_rdata[7:5];    //IP首部-标志字段:3位标志字段的第1位是保留位,第2位表示禁止分片(1表示不分片,0允许分片),第3位标识更多分片,通常为010不分片
                        ip_fragment_offset[12:8]            <=  I_ip_rdata[4:0];    //IP首部-片偏移:13位片偏移,在接收方进行数据报重组时用来标识分片的顺序。
                        cnt <=  cnt + 1'b1;
                    end 
                    6:  begin   ip_fragment_offset[7:0]     <=  I_ip_rdata; cnt <=  cnt + 1'b1;end  //IP首部-片偏移:13位片偏移,在接收方进行数据报重组时用来标识分片的顺序。
                    7:  begin   ip_packet_ttl[7:0]          <=  I_ip_rdata; cnt <=  cnt + 1'b1;end  //IP首部-生存时间:8位生存时间防止丢失的数据包在无休止的传播,一般被设置为64或者128
                    8:  begin   ip_packet_protocol[7:0]     <=  I_ip_rdata; cnt <=  cnt + 1'b1;end  //IP首部-协议:8位协议类型表示此数据报所携带上层数据使用的协议类型,ICMP为1,TCP为6,UDP为17    
                    9:  begin   ip_header_checksum[15:8]    <=  I_ip_rdata; cnt <=  cnt + 1'b1;end  //IP首部-首部校验和:16位首部校验和,该字段只校验数据报的首部,不包含数据部分
                    10: begin   ip_header_checksum[7:0]     <=  I_ip_rdata; cnt <=  cnt + 1'b1;end  //IP首部-首部校验和:16位首部校验和,该字段只校验数据报的首部,不包含数据部分
                    11: begin   ip_src_address[31:24]       <=  I_ip_rdata; cnt <=  cnt + 1'b1;end  //IP首部-源IP地址:32位发送端的IP地址
                    12: begin   ip_src_address[23:16]       <=  I_ip_rdata; cnt <=  cnt + 1'b1;end  //IP首部-源IP地址:32位发送端的IP地址
                    13: begin   ip_src_address[15:8]        <=  I_ip_rdata; cnt <=  cnt + 1'b1;end  //IP首部-源IP地址:32位发送端的IP地址
                    14: begin   ip_src_address[7:0]         <=  I_ip_rdata; cnt <=  cnt + 1'b1;end  //IP首部-源IP地址:32位发送端的IP地址
                    15: begin   ip_dst_address[31:24]       <=  I_ip_rdata; cnt <=  cnt + 1'b1;end  //IP首部-目的IP地址:32位接收端的IP地址
                    16: begin   ip_dst_address[23:16]       <=  I_ip_rdata; cnt <=  cnt + 1'b1;end  //IP首部-目的IP地址:32位接收端的IP地址
                    17: begin   ip_dst_address[15:8]        <=  I_ip_rdata; cnt <=  cnt + 1'b1;end  //IP首部-目的IP地址:32位接收端的IP地址
                    18: begin   
                        ip_dst_address[7:0]         <=  I_ip_rdata;                         //IP首部-目的IP地址:32位接收端的IP地址
                        cnt                         <=  5'd0;
                        if({ip_dst_address[31:8], I_ip_rdata} == I_ip_local_addr) begin     //如果收到的IP地址和本地IP地址匹配
                            if(ip_packet_protocol == ICMP_TYPE) begin                       //如果是ICMP类型
                                icmp_pkg_valid      <=  1'b1;                               //ICMP包有效           
                                STATE               <=  WAIT_PACKET_END;                    //等待传输结束状态
                            end
                            else if(ip_packet_protocol == UDP_TYPE) begin                   //如果是UDP包有效 
                                icmp_pkg_valid      <=  1'b0;
                                STATE               <=  OUTPUT_UDP_PACKET;                  //输出UDP包到UDP协议层
                            end
                            else begin
                                icmp_pkg_valid      <=  1'b0;
                                STATE               <=  WAIT_PACKET_END;                    //等待传输结束状态
                            end
                        end
                        else begin
                            icmp_pkg_valid          <=  1'b0;
                            STATE                   <=  WAIT_PACKET_END;                    //等待传输结束状态
                        end
                    end 
                endcase
            end
            OUTPUT_UDP_PACKET:begin
                if(I_ip_rvalid) begin       //打拍后支持输出给UDP协议层
                    O_udp_ip_rvalid         <=  1'b1;
                    O_udp_ip_rdata          <=  I_ip_rdata;
                    STATE                   <=  OUTPUT_UDP_PACKET;
                end
                else begin
                    O_udp_ip_rvalid         <=  1'b0;
                    O_udp_ip_rdata          <=  8'd0;
                    STATE                   <=  WAIT_IP_PACKET;                 
                end     
            end
            WAIT_PACKET_END:begin           //等待包传输结束
                if(I_ip_rvalid)
                    STATE                   <=  WAIT_PACKET_END;
                else begin
                    icmp_pkg_valid          <=  1'b0;
                    STATE                   <=  WAIT_IP_PACKET;
                end     
            end
        endcase
    end     
end

3.3.2 IP发送模块

该模块的主要功能有:接收uiudp_tx发送的UDP报文和uiip_rx发送的ICMP报文信息,将其封装成IP包并发送至下层uiip_arp_tx模块。

该模块的状态机转换图如图所示。

IDLE:uiip_tx模块处于发送空闲时,接收ICMP和UDP报文发送请求,优先响应ICMP请求。当收到请求时,向uiip_arp_tx模块发送请求信号,通过udp_pkg_en信号标记报文类型,进入WAIT_ACK状态,等待握手响应信号。

WAIT_ACK:接收到I_ip_tbusy信号,代表和IP_ARP层模块握手成功,可以发送数据,进入SEND_IP_HEADER状态。若要发送的是UDP报文,则会发送O_ip_udp_tbusy信号和UDP层进行握手。

SEND_IP_HEADER:在有效数据报文前添加对应的IP包头,发送包头完毕后,若报文类型为UDP报文,进入SEND_UDP_PACKET状态;若为ICMP报文,则进入SEND_ICMP_PACKET状态。

SEND_UDP_PACKET和SEND_ICMP_PACKET:发送完报文中的有效数据后,将标识加1,回到IDLE状态。

case(STATE)
            IDLE:begin
                if(icmp_pkg_req & (~I_ip_tbusy)) begin          //如果有ICMP包需要发送,并且ip_arp_tx模块处于空闲(I_ip_tbusy==0代表tbuf空闲,不在发送数据)
                    O_ip_treq           <=  1'b1;               //通知ip_arp_tx模块,有IP包需要发送(ICMP包也是IP包)
                    O_ip_udp_tbusy      <=  1'b0;               //通知udp_layer模块,目前不能发送UDP数据包
                    O_ip_taddr          <=  icmp_pkg_ip_addr;   //保存ip_rx模块接收到的icmp请求的IP地址(因为发送icmp包需要通过IP地址获取远程主机的MAC地址)
                    udp_pkg_en          <=  1'b0;               //标记是否是udp包,但udp_pkg_en=1 代表ip层发送的数据为UDP包
                    STATE               <=  WAIT_ACK;
                end
                else if(I_ip_udp_treq & (~I_ip_tbusy)) begin    //如果有UDP包需要发送
                    O_ip_treq           <=  1'b1;               //输出ip包发送请求,给ip_arp_tx模块
                    O_ip_udp_tbusy      <=  1'b0;               //通知udp_layer模块,目前不能发送UDP数据包
                    O_ip_taddr          <=  I_ip_dest_addr;     //udp层提供需要发送的目的主机的IP地址
                    udp_pkg_en          <=  1'b1;               //标记是否是udp包,但udp_pkg_en=1 代表ip层发送的数据为UDP包
                    STATE               <=  WAIT_ACK;
                end
                else begin
                    O_ip_udp_tbusy      <=  1'b0;
                    O_ip_treq           <=  1'b0;
                    udp_pkg_en          <=  1'b0;
                    STATE               <=  IDLE;
                end
            end
            WAIT_ACK:begin
                if(I_ip_tbusy) begin//当发送O_ip_treq后,如果ip_arp_tx模块返回I_ip_tbusy=1 代表ip_layer可以发送IP包(UDP包和ICMP包)到ip_arp_tx模块
                    O_ip_treq           <=  1'b0;
                    O_ip_udp_tbusy      <=  udp_pkg_en ? 1 : 0; //如果udp_pkg_en有效代表发的是UDP包
                    STATE               <=  SEND_IP_HEADER;     //发送IP帧头
                end
                else begin
                    O_ip_treq           <=  1'b1;
                    O_ip_udp_tbusy      <=  1'b0;
                    STATE               <=  WAIT_ACK;                   
                end
            end
            SEND_IP_HEADER:begin//发送IP包帧头
                case(cnt)
                    0   :begin
                        if(I_ip_udp_tvalid | (~udp_pkg_en)) begin       //如果是UDP报文包需要发送或者udp_pkg_en==0 是ICMP报文包
                            O_ip_tdata      <=  {VERSION, IHL};         //版本|首部长度(IP首部一共有多少个32bit数据)
                            O_ip_tvalid     <=  1'b1;                   //通知tbuf IP数据有效
                            packet_id       <=  ID_BASE + datagram_cnt; //标识,每发送1包该值加1
                            TTL             <=  8'h80;                  //生存时间  
                            if(!udp_pkg_en) begin                       //如果是ICMP包
                                ip_tdata_length     <=  icmp_pkg_data_len + (IHL << 2); //IP包总长度(IP数据长度+IP首部长度) 
                                PROTOCOL            <=  8'h01;                          //IP包类型为 ICMP包
                            end
                            else begin
                                ip_tdata_length     <=  I_ip_udp_tdata_len + (IHL << 2);
                                PROTOCOL            <=  8'h11;                          //IP包类型为 UDP包
                            end
                            cnt             <=  cnt + 1'b1;
                        end
                        else
                            cnt             <=  5'd0;
                    end
                    1   :begin  O_ip_tdata  <=  TOS;                            cnt <=  cnt + 1'b1;end//服务类型
                    2   :begin  O_ip_tdata  <=  ip_tdata_length[15:8];          cnt <=  cnt + 1'b1;end//IP包总长度
                    3   :begin  O_ip_tdata  <=  ip_tdata_length[7:0];           cnt <=  cnt + 1'b1;end//IP包总长度
                    4   :begin  O_ip_tdata  <=  packet_id[15:8];                cnt <=  cnt + 1'b1;end//IP包标识符,每发送一份报文,其值加1
                    5   :begin  O_ip_tdata  <=  packet_id[7:0];                 cnt <=  cnt + 1'b1;end//IP包标识符,每发送一份报文,其值加1
                    6   :begin  O_ip_tdata  <=  {FLAG, FRAGMENT_OFFSET[12:8]};  cnt <=  cnt + 1'b1;end//标志字段3bit|片偏移共13bit
                    7   :begin  O_ip_tdata  <=  FRAGMENT_OFFSET[7:0];           cnt <=  cnt + 1'b1;end//片偏移共13bit
                    8   :begin  O_ip_tdata  <=  TTL;                            cnt <=  cnt + 1'b1;end//生存时间
                    9   :begin  O_ip_tdata  <=  PROTOCOL;                       cnt <=  cnt + 1'b1;end//协议
                    10  :begin  O_ip_tdata  <=  checksum[15:8];                 cnt <=  cnt + 1'b1;end//校验和
                    11  :begin  O_ip_tdata  <=  checksum[7:0];                  cnt <=  cnt + 1'b1;end//校验和
                    12  :begin  O_ip_tdata  <=  I_ip_local_addr[31:24];         cnt <=  cnt + 1'b1;end//源IP地址32bit
                    13  :begin  O_ip_tdata  <=  I_ip_local_addr[23:16];         cnt <=  cnt + 1'b1;end//源IP地址32bit
                    14  :begin  O_ip_tdata  <=  I_ip_local_addr[15:8];          cnt <=  cnt + 1'b1;end//源IP地址32bit
                    15  :begin  O_ip_tdata  <=  I_ip_local_addr[7:0];           cnt <=  cnt + 1'b1;end//源IP地址32bit
                    16  :begin                          //目的IP地址(远端主机IP地址)
                        if(!udp_pkg_en)                 //ICMP报文包
                            O_ip_tdata      <=  icmp_pkg_ip_addr[31:24];
                        else                            //UDP报文包
                            O_ip_tdata      <=  O_ip_taddr[31:24];
                        cnt     <=  cnt + 1'b1;
                    end                 
                    17  :begin                          //目的IP地址(远端主机IP地址)
                        if(!udp_pkg_en)                 //ICMP报文包
                            O_ip_tdata      <=  icmp_pkg_ip_addr[23:16];
                        else                            //UDP报文包
                            O_ip_tdata      <=  O_ip_taddr[23:16];
                        cnt     <=  cnt + 1'b1;
                    end
                    18  :begin                          //目的IP地址(远端主机IP地址)
                        if(!udp_pkg_en) begin
                            O_ip_tdata      <=  icmp_pkg_ip_addr[15:8];
                            icmp_pkg_busy   <=  1'b1;//icmp_pkg_tx代码上必须时序上,在SEND_ICMP_PACKET状态输出ICMP报文包
                        end
                        else begin
                            O_ip_tdata      <=  O_ip_taddr[15:8];
                            icmp_pkg_busy   <=  1'b0;
                        end
                        cnt         <=  cnt + 1'b1;
                    end
                    19  :begin                          //目的IP地址(远端主机IP地址)
                        cnt <=  5'd0;
                        if(!udp_pkg_en) begin
                            O_ip_tdata      <=  icmp_pkg_ip_addr[7:0];
                            STATE           <=  SEND_ICMP_PACKET;
                        end
                        else begin
                            O_ip_tdata      <=  O_ip_taddr[7:0];
                            STATE           <=  SEND_UDP_PACKET;
                        end
                    end
                    default:    cnt <=  5'd0;
                endcase
            end
            SEND_UDP_PACKET:begin                   //发送UDP报文包
                if(trans_data_cnt == (ip_tdata_length - 16'd20)) begin  //20个字节为IP首部,这里相等代表数据发送结束   
                    O_ip_udp_tbusy      <=  1'b0;
                    O_ip_tvalid         <=  1'b0;
                    O_ip_tdata          <=  8'd0;
                    datagram_cnt        <=  datagram_cnt + 16'h0001;    //没发送完1帧报文,该值加1
                    trans_data_cnt      <=  16'd0;
                    STATE               <=  IDLE;
                end
                else begin                          //发送有效的UDP报文数据部分
                    O_ip_tvalid         <=  1'b1;
                    O_ip_tdata          <=  shift_data_out;         //从shift移位寄存器移出数据
                    trans_data_cnt      <=  trans_data_cnt + 1'b1;  //UDP报文包有效数据部分计数器
                    STATE               <=  SEND_UDP_PACKET;
                end
            end
            SEND_ICMP_PACKET:begin                  //发送ICMP报文包
                if(icmp_pkg_valid) begin
                    O_ip_tvalid         <=  1'b1;
                    O_ip_tdata          <=  icmp_pkg_data;
                    STATE               <=  SEND_ICMP_PACKET;
                end
                else begin
                    O_ip_tvalid         <=  1'b0;
                    O_ip_tdata          <=  8'd0;
                    icmp_pkg_busy       <=  1'b0;
                    datagram_cnt        <=  datagram_cnt + 16'h0001;//每发送完1帧报文,该值加1
                    STATE               <=  IDLE;                   
                end
            end
        endcase

3.3.3 IP首部校验模块

        正常计算IP首部校验和时,将校验位置0。由于每两字节数据相加得到的不再产生进位结果,为最终校验和的取反,所以当计算过程中加入校验位时,相加得到的结果应当为全1。若结果不为全1,则数据校验错误,将O_check_rerror信号置为高。

`timescale 1ns / 1ps

module ip_header_checksum(
input  wire         I_clk,
input  wire         I_reset,
input  wire         I_ip_rdata_valid,
input  wire [7:0]   I_ip_rdata,
output wire         O_checksum_rerror
);
reg checksum_correct;
assign O_checksum_rerror = ~checksum_correct;

reg [1:0]  state;
reg [3:0]  cnt;
wire [16:0] tmp_accum1;
reg [15:0] accum1, accum2;

assign tmp_accum1 = accum1 + accum2;

always @(posedge I_clk or posedge I_reset) begin
    if(I_reset) begin
        state               <= 2'd0;
        cnt                 <= 4'd0;
        accum1              <= 16'd0;
        accum2              <= 16'd0;       
        checksum_correct    <= 1'b1;            
    end
    else begin
        case(state) 
            0: begin 
                if(I_ip_rdata_valid) begin
                    accum1[15:8]            <= I_ip_rdata; 
                    state                   <= 2'd1; 
                end
                else begin
                    accum1[15:8]            <= 8'd0;
                    state                   <= 2'd0;
                end
            end
            1: begin accum1[7:0]    <= I_ip_rdata; state <= 2'd2; end
            2: begin        
                if(cnt == 4'd9) begin
                    if((tmp_accum1[15:0] + tmp_accum1[16]) != 16'hffff)
                        checksum_correct    <= 1'b0;
                    cnt                 <= 4'd0;
                    state               <= 2'd3;
                end
                else begin  
                    accum2 <= tmp_accum1[15:0] + tmp_accum1[16];
                    accum1[15:8]        <= I_ip_rdata;
                    cnt                 <= cnt + 1'b1;                         
                    state               <= 2'd1;
                end
            end
            3: begin
                accum1                  <= 16'd0;
                accum2                  <= 16'd0;
                if(I_ip_rdata_valid)
                    state       <= state;
                else
                    state       <= 2'd0;
                end             
        endcase
    end
end
endmodule

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1983486.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

全面解析PHP反序列化漏洞:原理、复现与防御

文章目录 概念序列化数据的含义魔术方法魔术方法的使用construct&#xff0c;destructtoStringcallgetsetsleepwakeupissetunsetinvoke 原生态反序列化漏洞概念种类复现 wakeup长度绕过产生原因条件复现 基本题型源码解读 在Web应用安全领域&#xff0c;PHP反序列化漏洞常常被视…

Tomcat 使用和配置文件(详解)

一.tomcat 介绍 1. tomcat 概述 自从JSP发布之后&#xff0c;推出了各式各样的JSP引擎。Apache Group在完成GNUJSP1.0的开发以后&#xff0c;开始考虑在SUN的JSWDK基础上开发一个可以直接提供Web服务的JSP服务器&#xff0c;当然同时也支持 Servlet&#xff0c;这样Tomcat就诞…

MySQL数据库误删恢复--超详细

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

Tensorflow——第三讲神经网络八股

前两讲我们学习了使用tensorflow原生代码搭建神经网络&#xff0c;本讲主要学习使用Tensorflow API&#xff1a;tf.keras搭建神经网络 一、搭建网络八股Sequential 六步法&#xff1a; 1.import&#xff1a;import 相关模块&#xff0c;如 import tensorflow as tf 2.train…

2024年7月30日~2024年8月5日周报

一、前言 上周继续修改论文&#xff0c;并阅读了两篇论文。 本周主要修改论文、完成实验、参加一些组会与论文讨论会&#xff0c;并配置了torch环境。 二、完成情况 2.1 论文符号系统注意事项 数学符号应该有唯一性&#xff0c;不能与其他符号造成误解&#xff1b;W_{\mathr…

c++初阶-----适配器---priority_queue

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

极狐GitLab CICD Catalog Beta 功能介绍

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门面向中国程序员和企业提供企业级一体化 DevOps 平台&#xff0c;用来帮助用户实现需求管理、源代码托管、CI/CD、安全合规&#xff0c;而且所有的操作都是在一个平台上进行&#xff0c;省事省心省钱。可以一键安装极狐GitL…

【Python】数据类型之列表(下)

&#xff08;6&#xff09;清空列表 功能&#xff1a;clear() 代码示例&#xff1a; &#xff08;7&#xff09;根据值获取索引&#xff08;从左到右找到第一个返回索引&#xff09;【慎用&#xff0c;找不到报错】 功能&#xff1a;index(xyz)&#xff0c;xyz为数据类型。 …

OpenAI gym player mode

题意&#xff1a;OpenAI gym 的自定义模式 问题背景&#xff1a; Does anyone know how to run one of the OpenAI gym environments as a player. As in letting a human player play a round of cart pole? I have seen that there is env.mode human but I have not been…

波兰表达式求值

from operator import add, sub, muldef div(x, y):# 使用整数除法的向零取整方式return int(x / y) if x * y > 0 else -(abs(x) // abs(y))class Solution(object):op_map {: add, -: sub, *: mul, /: div}def evalRPN(self, tokens: List[str]) -> int:stack []for …

【C基础-按要求找数】一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少

一个整数&#xff0c;它加上100后是一个完全平方数&#xff0c;再加上168又是一个完全平方数&#xff0c;请问该数是多少 完全平方数是指一个整数能够表示为某个整数的平方。换句话说&#xff0c;如果存在一个整数 n&#xff0c;使得 n^2m,那么 m 就是一个完全平方数。 使用C…

第二十一天培训笔记

上午 1 、环境准备 2 、安装 mysql 绿包 3 、配置 mysql 工作环境 mysql -hip 地址 -p3306 -uroot -p &#xff08;远程连接使用&#xff09; 4 、 mysql 基础命令 &#xff08; 1 &#xff09;修改密码 &#xff08; 2 &#xff09;授权远程登录 &#xff08; 3 &#x…

程序员短视频上瘾综合症

一、是你疯了还是面试官疯了&#xff1f; ​ 最近有两个学员咨询问题&#xff0c;把我给整得苦笑不得。大家来看看&#xff0c;你有没有同样的症状。 ​ 第一个学员说去一家公司面试&#xff0c;第一轮面试聊得挺好的。第二轮面试自我感觉良好&#xff0c;但是被面试官给Diss…

模型优化学习笔记—对比各种梯度下降算法

import mathimport numpy as np from opt_utils import * import matplotlib.pyplot as plt# 标准梯度下降 def update_parameters_with_gd(parameters, grads, learning_rate):L len(parameters) // 2for l in range(1, L 1):parameters[f"W{l}"] parameters[f&q…

【uniapp】聊天记录列表长按消息计算弹出菜单方向

1. 效果图 1.1 消息靠上接近导航栏&#xff0c;菜单显在消息体下方弹出&#xff0c;箭头向上 1.2 消息体没有贴近上方导航栏&#xff0c;菜单在消息体上方弹出&#xff0c;箭头向下 1.3 长消息&#xff0c;菜单在手指按下的位置弹出&#xff0c;无箭头 2. 代码实现 <view …

sqli 1- 10

sql靶场 第一关 首先我们需要判断是否存在sql注入点&#xff0c;前端界面提示我使用ID作为参数,在url地址栏输入?id1 通过输入不同的id值查询数据库相对应的内容&#xff0c;之后判断为数字型还是字符型 根据查询内容判断为字符型且有注入点&#xff0c;再通过联合查询&…

Vitis AI 基本操作+模型检查(inspector)用法详解

目录 1. 简介 2. 代码详解 2.1 导入所需的库 2.2 创建 Inspector 2.3 下载模型 2.4 检查模型 3. 其他有用函数 3.1 查看 torchvision 中模型 3.2 保存模型 3.2.1 保存模型参数 3.2.2 保存完整模型 3.2.3 加载模型 4. 总结 1. 简介 在《Vitis AI 构建开发环境&…

GNSS相关知识

各定位系统的频段&#xff1a; SystemSignalFrequency(MHz)GPSL1C/A1575.42L1C1575.42L2C1227.6L2P1227.6L51176.45   GLONASSL1C/A1598.0625-1609.3125L2C1242.9375-1251.6875L2P1242.9375-1251.6875L3OC1202.025   GalileoE11575.42E5a1176.45E5b1207.14E5AltBOC1191.…

SpringBoot之外部化配置

前言 SpringBoot 版本 2.6.13&#xff0c;相关链接 Core Features Default properties (specified by setting SpringApplication.setDefaultProperties).PropertySource annotations on your Configuration classes. Please note that such property sources are not added …

如何在群晖NAS中搭建影音管理利器nastool并实现远程访问本地资源

文章目录 前言1. 本地搭建Nastool2. nastool基础设置3. 群晖NAS安装内网穿透工具4. 配置公网地址5. 配置固定公网地址 前言 Nastool是为群晖NAS玩家量身打造的一款智能化影音管理利器。它不仅能够满足电影发烧友、音乐爱好者和追剧达人的需求&#xff0c;更能让你在繁忙的生活…