以太网UDP:心跳包、ICMP与ARP
参考:
https://juejin.cn/post/6844903951452602375
心跳包
- UDP:用户数据报协议:主要用在实时性要求比较高的以及对质量相对较弱的地方.但是面对现在高质量的线路不会容易丢包,除非是一些拥塞条件下,如流媒体
- TCP:传输控制协议:是面连接的那么运行环境必然要求其可靠性不可丢包,有良好的拥塞控制机制如 http ftp telnet等。
网络中的接收和发送数据都是使用操作系统中的SOCKET进行实现。
但是如果此套接字已经断开,那发送数据和接收数据的时候就一定会有问题。
可是如何判断这个套接字是否还可以使用呢?这个就需要在系统中创建心跳机制。
其实TCP中已经为我们实现了一个叫做心跳的机制。
如果你设置了心跳,那TCP就会在一定的时间(比如你设置的是3秒钟)内发送你设置的次数的心跳(比如说2次),并且此信息不会影响你自己定义的协议。
所谓“心跳”就是定时发送一个自定义的结构体(心跳包或心跳帧),让对方知道自己“在线”。以确保链接的有效性。
所谓的心跳包就是客户端定时发送简单的信息给服务器端告诉它我还在而已。
代码就是每隔几分钟发送一个固定信息给服务端,服务端收到后回复一个固定信息如果服务端几分钟内没有收到客户端信息则视客户端断开。
比如有些通信软件长时间不使用,要想知道它的状态是在线还是离线就需要心跳包,定时发包收包。
发包方可以是客户也可以是服务端,看哪边实现方便合理。一般是客户端。服务器也可以定时轮询发心跳下去。
心跳包之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着。
事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很小的包,或者只包含包头的一个空包。
在TCP的机制里面,本身是存在有心跳包的机制的,也就是TCP的选项。系统默认是设置的是2小时的心跳频率。
但是它检查不到机器断电、网线拔出、防火墙这些断线。而且逻辑层处理断线可能也不是那么好处理。
一般,如果只是用于保活还是可以的。心跳包一般来说都是在逻辑层发送空的包来实现的。
下一个定时器,在一定时间间隔下发送一个空包给客户端,然后客户端反馈一个同样的空包回来,服务器如果在一定时间内收不到客户端发送过来的反馈包,那就只有认定说掉线了。
只需要send或者recv一下,如果结果为零,则为掉线。
但是,在长连接下,有可能很长一段时间都没有数据往来。
理论上说,这个连接是一直保持连接的,但是实际情况中,如果中间节点出现什么故障是难以知道的。
更要命的是,有的节点(防火墙)会自动把一定时间之内没有数据交互的连接给断掉。在这个时候,就需要我们的心跳包了,用于维持长连接,保活。
在获知了断线之后,服务器逻辑可能需要做一些事情,比如断线后的数据清理呀,重新连接呀当然,这个自然是要由逻辑层根据需求去做了。
总的来说,心跳包主要也就是用于长连接的保活和断线处理。一般的应用下,判定时间在30-40秒比较不错。如果实在要求高,那就在6-9秒。
心跳检测步骤:
1.客户端每隔一个时间间隔发生一个探测包给服务器
2.客户端发包时启动一个超时定时器
3.服务器端接收到检测包,应该回应一个包
4.如果客户机收到服务器的应答包,则说明服务器正常,删除超时定时器
5.如果客户端的超时定时器超时,依然没有收到应答包,则说明服务器挂了
Heartbeat和ARP的差别
Heartbeat(心跳包)和ARP(地址解析协议,Address Resolution Protocol)之间存在本质上的区别,它们在网络中扮演着不同的角色并服务于不同的目的。
Heartbeat(心跳包)
- 用途:Heartbeat机制主要用于监测网络中的两个点(例如,两台服务器或客户端和服务器之间)的连通性。通过定期发送小的数据包(即心跳包)来确认对方是否在线和可响应。这种机制广泛用于高可用性系统中,以确保系统组件间的持续通信,并快速检测故障。
- 层级:心跳包可以在多种网络层级上实现,包括应用层、传输层(TCP/UDP)或更低的网络层。
ARP(地址解析协议)
- 用途:ARP的目的是解决网络层到链路层地址的映射问题。在IPv4网络中,当一个设备需要向同一局域网(LAN)内的另一个设备发送数据时,它需要将目标设备的IP地址转换为物理MAC地址。ARP允许任何设备广播一个请求,来询问具有特定IP地址的设备的MAC地址。
- 层级:ARP工作在链路层,直接与网络接口卡(NIC)交互,以解析网络层的IP地址到链路层的MAC地址。
主要差别
- 目的不同:Heartbeat用于监控和维护网络连接的状态,而ARP用于解析网络地址到物理地址。
- 工作原理不同:Heartbeat通过发送和接收简单的消息包来检测网络连通性;ARP通过广播请求来查询特定IP地址对应的MAC地址,并接收回应。
- 应用场景不同:Heartbeat多用于确保高可用性和故障转移场景中的设备或服务连通性,ARP是局域网内部设备进行通信的基础服务。
总的来说,Heartbeat和ARP服务于网络通信的不同方面,Heartbeat关注于连接的持续性和可靠性,而ARP解决的是如何在网络中准确地定位和通信到特定的设备。
Heartbeat与ICMP的异同
ICMP用于实现类似心跳包操作的ping
命令和其他类型的心跳包机制之间存在一些关键的相似之处和差异。下面是它们之间的一些主要异同点:
相似之处
- 连通性检测:ICMP的
ping
命令和心跳包都被用来检测网络中的设备是否可达,即对方是否在线且网络连接是否正常。 - 基于消息的简单请求-响应模型:无论是ICMP的
ping
操作还是其他心跳机制,通常都采用了简单的请求-响应模型来实现。发送方发送一个请求(或心跳包),并等待接收方的响应。 - 网络诊断工具:它们都可以作为网络诊断的工具,帮助识别网络中的问题,比如路由问题、延迟、丢包等。
差异
- 协议层级:ICMP是一个网络层协议,直接由IP层处理,主要用于传递控制消息。而心跳包可以在不同的层级实现,如应用层(通过特定的应用协议发送心跳)、传输层(TCP/UDP)或甚至是会话层。
- 用途和功能:ICMP除了可以用于实现
ping
操作外,还设计用来传递网络通信过程中遇到的问题和控制消息,如目标不可达、时间超时等。心跳包的主要用途是保持网络连接的活跃状态,监测对方是否在线,以及在一些系统中用于负载均衡和故障转移。 - 数据包结构和内容:ICMP消息有其特定的格式,包括类型、代码和校验和等字段,用于不同类型的控制消息。心跳包的结构更加灵活,根据其设计的目的和所在的协议层级,可以包含从简单到复杂的各种信息,如状态信息、序列号、时间戳等。
- 反馈信息的详细程度:ICMP错误消息可以提供关于网络问题的详细信息,而心跳包机制的反馈通常仅限于确认对方是否活跃或响应。
总的来说,ICMP的ping
操作和心跳包机制都是网络通信中用于确保连通性和监测网络状态的重要工具。它们在实现方法、用途、以及操作层级上存在一些关键的差异,但共同目标是帮助管理和维护网络的稳定性和可靠性。
心跳包的结构
参考设计:
数据部分填入64字节的0。
代码:
module encode_heartbeat #( parameter UDP_CODE = 8'h11 , parameter TX_TARGET_PORT = 16'd0808, parameter TX_SOURCE_PORT = 16'd8080, parameter RX_Sync_Frame = 32'hF05AA50F, parameter TX_SOURCE_Addr = 32'd192_168_0_1, parameter TX_TARGET_Addr = 32'hFF_FF_FF_FF, //Length parameter TX_PREAMBLE = 64'h55_55_55_55_55_55_55_D5, parameter TX_TARGET_MAC = 48'hFF_FF_FF_FF_FF_FF ,// broadcast packet parameter TX_SOURECE_MAC = 48'hA8_B2_3C_7D_97_D7 , parameter Length_HeartBeat = 16'd92 , parameter Length_UDP = 16'd72 , parameter Length_HeartBeat_all = 8'd114 )( input wire sys_clk , input wire sys_rst_n , output wire rgmii_tx_hb_vaild , output wire [7:0] rgmii_tx_hb_data ); //-------------------------------------------------------------------------------------------// wire Gen_Start ; reg r1_Gen_Start ; reg r2_Gen_Start ; reg Gen_cycle ; reg r_tx_hb_vaild; reg [7:0] Gen_cnt ; reg [7:0] r_tx_hb_data ; //-------------------------------------------------------------------------------------------// timer_1s #( .cnt_1us ( 'd125 ), .cnt_1ms ( 'd10 ), .cnt_1s ( 'd10 )) u_timer_1s ( .sys_125mhz_clk ( sys_clk ), .sys_rst_n ( sys_rst_n ), .time_arrival ( Gen_Start ) ); //-------------------------------------------------------------------------------------------// assign rgmii_tx_hb_vaild = r_tx_hb_vaild; assign rgmii_tx_hb_data = r_tx_hb_data; always @(posedge sys_clk) begin if(sys_rst_n == 1'b0) begin Gen_cycle <= 1'b0; end else if(Gen_cycle == 1'b1 && Gen_cnt == Length_HeartBeat_all - 1'b1) begin Gen_cycle <= 1'b0; end else if(r1_Gen_Start == 1'b1 && r2_Gen_Start == 1'b0 && Gen_cycle == 1'b0) begin Gen_cycle <= 1'b1; end end always @(posedge sys_clk) begin r_tx_hb_vaild <= Gen_cycle; r1_Gen_Start <= Gen_Start; r2_Gen_Start <= r1_Gen_Start; end always @(posedge sys_clk) begin if(sys_rst_n == 1'b0) begin Gen_cnt <= 'd0; end else if(Gen_cycle == 1'b1 && Gen_cnt == Length_HeartBeat_all - 1'b1) begin Gen_cnt <= 'd0; end else if(Gen_cycle == 1'b1) begin Gen_cnt <= Gen_cnt + 1'b1; end end always @(posedge sys_clk) begin if(sys_rst_n == 1'b0) begin r_tx_hb_data <= 8'h00; end else if(Gen_cycle == 1'b1) begin case (Gen_cnt) 0,1,2,3,4,5,6,7:begin r_tx_hb_data <= TX_PREAMBLE[(63 - (Gen_cnt<<3))-:8]; end 8,9,10,11,12,13:begin r_tx_hb_data <= TX_TARGET_MAC[(47 - ((Gen_cnt-8)<<3))-:8]; end 14,15,16,17,18,19:begin r_tx_hb_data <= TX_SOURECE_MAC[(47 - ((Gen_cnt-14)<<3))-:8]; end 20:begin r_tx_hb_data <= 8'h08;//20-21 type ip end 21:begin r_tx_hb_data <= 8'h00;//20-21 type ip end 22:begin r_tx_hb_data <= 8'h45;//22-23 packet flag end 23:begin r_tx_hb_data <= 8'h00;//22-23 packet flag end 24:begin r_tx_hb_data <= Length_HeartBeat[15:08]; end 25:begin r_tx_hb_data <= Length_HeartBeat[08:00]; end 26:begin r_tx_hb_data <= 8'h00;//26-27:tos end 27:begin r_tx_hb_data <= 8'h00;//26-27:tos end 28:begin r_tx_hb_data <= 8'h00;//28-29 offset end 29:begin r_tx_hb_data <= 8'h00;//28-29 offset end 30:begin r_tx_hb_data <= 8'h80;//30 ttl end 31:begin r_tx_hb_data <= 8'h11;//31 udp flag end 32:begin r_tx_hb_data <= 8'h00;//32 -33 header check end 33:begin r_tx_hb_data <= 8'h00;//32 -33 header check end 34,35,36,37:begin r_tx_hb_data <= TX_SOURCE_Addr[(31 - ((Gen_cnt-34)<<3))-:8]; end 38,39,40,41:begin r_tx_hb_data <= TX_TARGET_Addr[(31 - ((Gen_cnt-38)<<3))-:8]; end 42:begin r_tx_hb_data <= TX_SOURCE_PORT[15:08]; end 43:begin r_tx_hb_data <= TX_SOURCE_PORT[07:00]; end 44:begin r_tx_hb_data <= TX_TARGET_PORT[15:08]; end 45:begin r_tx_hb_data <= TX_TARGET_PORT[07:00]; end 46:begin r_tx_hb_data <= Length_UDP[15:08]; end 47:begin r_tx_hb_data <= Length_UDP[07:00]; end default: begin r_tx_hb_data <= 8'h00; end endcase end else begin r_tx_hb_data <= 8'h00; end end endmodule