FPGA实现CAN通信

article/2025/8/30 0:32:32

FPGA实现CAN通信
1、CAN协议物理层和协议层
2、传输的波特率
3、FPGA实现思路
4、FPGA实现代码

1、CAN物理层和协议层
CAN与串口类似,都是异步通信,利用两根差分线来进行信号的传输。
在多节点进行数据传输时主要分为遵循ISO11898标准的高速短距离闭环形式和遵循ISO11519标准的低速远距离开环网络。这两种形式主要是在硬件设计时根据实际应用情况加入120欧姆或者2.2千欧姆电阻。
在CAN通信时信号逻辑和平时常用的电平表示不太一样,根据标准电平表示形式如下图:
在这里插入图片描述
在这里插入图片描述
CAN报文类型有5种,分别是数据帧、遥控帧、错误帧、过载帧、帧间隔。而我们常用的是数据帧,数据帧分为标准数据帧和扩展数据帧两种。数据帧结构如下图:
在这里插入图片描述
数据帧是以一个下降沿的电平来开始界定开始的。以7个连续隐性电平结束的。数据帧中间包含帧起始、仲裁段、控制段、数据段、CRC段、ACK段和帧结束段。
帧起始SOF段(Start Of Frame),帧起始信号只有一个数据位,是一个显性电平,它用于监测数据传输的开始,通过电平跳变沿来进行数据起始位的确定。
仲裁段:内容是数据帧的ID信息,标准帧ID长度是11位,扩展帧为18位。CAN 协议不对挂载在它之上的节点分配优先级和地址,对总线的占有权是由帧的ID决定的,对于重要信息给与一个优先级较高的ID,这样数据就能及时的发送出去。而ID优先级的仲裁原则是由物理层决定的,总线状态总是显性电平掩盖隐形电平,因此显性ID优先级较高。
仲裁段还包括(1)RTR 位(Remote Transmission Request Bit),译作远程传输请求位,它是用于区分数据帧和遥控帧的,当它为显性电平时表示数据帧,隐性电平时表示遥控帧。
(2) IDE 位(Identifier Extension Bit),译作标识符扩展位,它是用于区分标准格式与扩展格式,当它为显性电平时表示标准格式,隐性电平时表示扩展格式。
(3) SRR 位(Substitute Remote Request Bit),只存在于扩展格式,它用于替代标准格式中的
RTR 位。由于扩展帧中的SRR 位为隐性位,RTR 在数据帧为显性位,所以在两个ID相同的标准格式报文与扩展格式报文中,标准格式的优先级较高。
控制段:在控制段中的r1 和r0 为保留位,默认设置为显性位。它最主要的是DLC 段(Data
Length Code),译为数据长度码,它由4 个数据位组成,用于表示本报文中的数据段含有多
少个字节,DLC 段表示的数字为0~8。
数据段:数据段为数据帧的核心内容,它是节点要发送的原始信息,由0~8 个字节组成,MSB先行。
CRC 段:为了保证报文的正确传输,CAN 的报文包含了一段15 位的CRC 校验码,一旦接收节点算出的CRC 码跟接收到的CRC 码不同,则它会向发送节点反馈出错信息,利用错误帧请求它重新发送。CRC 部分的计算一般由CAN 控制器硬件完成,出错时的处理则由软件控制最大重发数。
ACK 段:ACK 段包括一个ACK 槽位,和ACK 界定符位。类似I2C 总线,在ACK 槽位中,发送节点发送的是隐性位,而接收节点则在这一位中发送显性位以示应答。在ACK 槽和帧结束之间由ACK 界定符间隔开。
帧结束EOF 段(End Of Frame),帧结束段由发送节点发送的7 个隐性位表示结束。

2、传输的波特率
CAN由于是异步通信,通信波特率与串口波特率定义类似,波特率的定义有每个子的长度来确定的。CAN的通信距离与波特率存在负相关关系,波特率越高,传输距离越短。CAN通信波特率与传输距离关系如下图:
在这里插入图片描述
3、FPGA实现思路
在进行FPGA实现时主要是实现一个完备的状态转移状态机。在设计状态机时需要对最复杂的包格式进行设计。通过对控制段进行判断来跳转到不同类型帧格式的状态,根据数据长度来完成对数据的接收和发送。由于FPGA实现完备的CAN收发驱动并不是所有项目所必须的,因此根据不同项目来进行特定包数据的收发。
通过上面描述对CAN数据格式有了一个基本上认识,下面是通过示波器抓取CAN标准数据帧波形,示波器正连接CANH端,示波器负极连接CANL端。波特率是10Kbps,有效数据长度8字节。
在这里插入图片描述

CAN数据收发架构设计如下图:
在这里插入图片描述
4、FPGA实现代码

在实现波特率可调的数据收发控制时需要注意的是每个波特数据的采样点。CAN数据采样时序如下图所示,一般采样点都是在数据稳当的中间点位置,因此在设计FPGA中CAN模块的时钟频率应当是数据波特率的20倍。
在这里插入图片描述
在以10Kbps采样率位例,CAN收发模块时钟设计如下:

//	
//数据速率位10Kbps,一个数据位时间为10us.数据采集在5us时刻。	
CAN波特率设置	
reg			[7:0]		can_div			;		//500倍分频,一个数据位分为20份
reg						can_clk			;	always @(posedge clk_100m or negedge rst_n )begin
if(rst_n==1'b0) begin
can_div	<= 'b0							;
end else if (can_div==249) begin
can_div	<= 'b0							;
end	else  begin 
can_div	<= can_div + 1'b1				;
end	
end 	always @(posedge clk_100m or negedge rst_n )begin
if(rst_n==1'b0) begin
can_clk	<= 'b0							;
end else if (can_div==249) begin
can_clk	<= can_clk + 1'b1				;
end	
end//时钟经过BUFG缓冲
wire				can_clk_o		;  
BUFG   can_clk_obuf (.I(can_clk), .O(can_clk_o));

数据的收发需要根据实际的项目情况进行组包控制,这里就不进行细致描述了。
CAN实现数据的收发两个过程中对应FPGA来说由于接收相对复杂,就以接收模块进行描述。
数据的接收过程就按照一般的状态机进行设计就行,需要注意的是不同类型帧的跳转是在控制段进行了,因此在控制段会发生状态的跳转。CAN接收状态的状态机实现如下图:
在这里插入图片描述

这个状态机的实现并不复杂,主要是对帧类型进行判断。然后根据数据长度把数据解析出来。下面是实现CAN数据接收代码:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date:    
// Design Name: 
// Module Name:    can_rx 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//
module can_rx(input   	wire		                can_clk	    				,
input   	wire		                rst_n       				,input		wire						can_rx						,output		reg							can_ack_out_low				,
output		reg							can_id_out_en				,
output		reg			[10:0]			can_id_out					,
output		reg							can_data_out_en				,
output		reg			[63:0]			can_data_out		);		reg					[8:0]			state							;
reg									can_rx_t						;
reg									error_state						;
reg					[9:0]			error_data						;
reg					[4:0]			one_bit_cont					;
reg					[10:0]			can_id							;
reg					[6:0]			bit_cont						;
reg									id_en_flag						;
reg									contral_flag					;
reg									data_en_flag					;
reg									cic_en_flag						;
reg									can_rx_en_flag					;
reg									can_rx_unen_flag				;
reg					[4:0]			can_continuity_data				;
reg									can_continuity_data_flag		;
reg					[4:0]			can_id_data_cont				;
reg					[3:0]			can_contral_data_cont			;
reg					[6:0]			can_data_data_cont				;
reg					[4:0]			can_cic_data_cont				;always @(posedge can_clk or negedge rst_n )begin
if(rst_n==1'b0) begin
can_rx_t	<= 'b0							;
end else  begin
can_rx_t	<= can_rx						;
end	
end parameter			state_idle		 = 9'b000000000			;			//状态机初始化
parameter			state_start		 = 9'b000000001			;			//监测到开始标志
parameter			state_sof		 = 9'b000000010			;           //开始帧头第一位SOF
parameter			state_id		 = 9'b000000100			;           //包ID
parameter			state_control	 = 9'b000001000			;           //标准帧控制段
parameter			state_data		 = 9'b000010000			;           //数据段
parameter			state_crc		 = 9'b000100000			;           //CRC段
parameter			state_ack		 = 9'b001000000			;           //ACK段
parameter			state_eof		 = 9'b010000000			;           //帧结束段
parameter			state_end		 = 9'b100000000			;           //状态机结束状态parameter			bit_flag_no		 = 5'b10011				;		always @(posedge can_clk or negedge rst_n )begin
if(rst_n==1'b0) begin
state						<= 'b0							;
one_bit_cont				<= 'b0							;
bit_cont					<= 'b0							;
id_en_flag					<= 'b0							;
contral_flag				<= 'b0							;
data_en_flag                <= 'b0							;
cic_en_flag					<= 'b0							;
can_rx_en_flag              <= 'b0							;
can_ack_out_low				<= 'b1							;
end   else case(state) state_idle:		begin if ((can_rx_t==1'b1)&&(can_rx==1'b0))	beginstate						<= state_sof					;one_bit_cont				<= 'b0							;can_rx_en_flag              <= 'b1							;end else beginstate						<= state_idle					;one_bit_cont				<= 'b0							;bit_cont					<= 'b0							;id_en_flag					<= 'b0							;contral_flag                <= 'b0							;data_en_flag				<= 'b0							;cic_en_flag	                <= 'b0							;can_rx_en_flag              <= 'b0							;can_ack_out_low				<= 'b1							;end end state_sof:		begin if ((one_bit_cont==bit_flag_no)&&(can_rx==1'b0))	beginstate						<= state_id						;id_en_flag					<= 'b1							;one_bit_cont				<= 'b0							;end else if ((one_bit_cont<bit_flag_no)&&(can_rx==1'b0)) beginstate						<= state_sof					;one_bit_cont				<= one_bit_cont + 1'b1			;end end state_id:		begin if ((one_bit_cont==bit_flag_no)&&(bit_cont==can_id_data_cont))	beginstate						<= state_control				;id_en_flag					<= 'b0							;contral_flag				<= 'b1							;one_bit_cont				<= 'b0							;bit_cont					<= 'b0							;end else if ((one_bit_cont==bit_flag_no)&&(bit_cont<can_id_data_cont)) beginstate						<= state_id						;one_bit_cont				<= 'b0							;bit_cont					<= bit_cont + 1'b1				;end else if (one_bit_cont<bit_flag_no) beginstate						<= state_id						;one_bit_cont				<= one_bit_cont + 1'b1			;end else beginstate						<= state_idle					;end end state_control:	begin if ((one_bit_cont==bit_flag_no)&&(bit_cont==can_contral_data_cont))	beginstate						<= state_data					;contral_flag				<= 'b0							;one_bit_cont				<= 'b0							;bit_cont					<= 'b0							;data_en_flag                <= 'b1							;end else if ((one_bit_cont==bit_flag_no)&&(bit_cont<can_contral_data_cont)) beginstate						<= state_control				;one_bit_cont				<= 'b0							;bit_cont					<= bit_cont + 1'b1				;end else if (one_bit_cont<bit_flag_no) beginstate						<= state_control				;one_bit_cont				<= one_bit_cont + 1'b1			;end else beginstate						<= state_idle					;end end state_data:	begin if ((one_bit_cont==bit_flag_no)&&(bit_cont==can_data_data_cont))	beginstate						<= state_crc					;one_bit_cont				<= 'b0							;bit_cont					<= 'b0							;data_en_flag                <= 'b0							;cic_en_flag					<= 'b1							;end else if ((one_bit_cont==bit_flag_no)&&(bit_cont<can_data_data_cont)) beginstate						<= state_data					;one_bit_cont				<= 'b0							;bit_cont					<= bit_cont + 1'b1				;end else if (one_bit_cont<bit_flag_no) beginstate						<= state_data					;one_bit_cont				<= one_bit_cont + 1'b1			;end else beginstate						<= state_idle					;end end state_crc:	begin if ((one_bit_cont==bit_flag_no)&&(bit_cont==can_cic_data_cont))	beginstate						<= state_ack					;can_ack_out_low				<= 'b0							;one_bit_cont				<= 'b0							;bit_cont					<= 'b0							;cic_en_flag					<= 'b0							;end else if ((one_bit_cont==bit_flag_no)&&(bit_cont<can_cic_data_cont)) beginstate						<= state_crc					;one_bit_cont				<= 'b0							;bit_cont					<= bit_cont + 1'b1				;end else if (one_bit_cont<bit_flag_no) beginstate						<= state_crc					;one_bit_cont				<= one_bit_cont + 1'b1			;end else beginstate						<= state_idle					;end end state_ack:	begin if ((one_bit_cont==bit_flag_no)&&(bit_cont==1))	beginstate						<= state_eof					;can_ack_out_low				<= 'b1							;one_bit_cont				<= 'b0							;bit_cont					<= 'b0							;end else if ((one_bit_cont==bit_flag_no)&&(bit_cont<1)) beginstate						<= state_ack					;one_bit_cont				<= 'b0							;bit_cont					<= bit_cont + 1'b1				;end else if (one_bit_cont<bit_flag_no) beginstate						<= state_ack					;one_bit_cont				<= one_bit_cont + 1'b1			;end else beginstate						<= state_idle					;end end state_eof:	begin if ((one_bit_cont==bit_flag_no)&&(bit_cont==5))	beginstate						<= state_end					;one_bit_cont				<= 'b0							;bit_cont					<= 'b0							;end else if ((one_bit_cont==bit_flag_no)&&(bit_cont<5)) beginstate						<= state_eof					;one_bit_cont				<= 'b0							;bit_cont					<= bit_cont + 1'b1				;end else if (one_bit_cont<bit_flag_no) beginstate						<= state_eof					;one_bit_cont				<= one_bit_cont + 1'b1			;end else beginstate						<= state_idle					;end end state_end:		begin state						<= state_idle					;one_bit_cont				<= 'b0							;bit_cont					<= 'b0							;id_en_flag					<= 'b0							;contral_flag                <= 'b0							;data_en_flag				<= 'b0							;cic_en_flag	                <= 'b0							;can_rx_en_flag              <= 'b0							;can_ack_out_low				<= 'b1							;end 			default:		begin state						<= state_idle					;one_bit_cont				<= 'b0							;bit_cont					<= 'b0							;id_en_flag					<= 'b0							;contral_flag                <= 'b0							;data_en_flag				<= 'b0							;cic_en_flag	                <= 'b0							;can_rx_en_flag              <= 'b0							;can_ack_out_low				<= 'b1							;end 	 endcase
end //always @(posedge can_clk or negedge rst_n )begin
//if(rst_n==1'b0) begin
//error_data	<= 'b0									;
//end else if (can_rx_en_flag==1) begin
//error_data	<= {error_data[9:0],can_rx	}				;
//end	else if (one_bit_cont==11) begin
//can_rx_unen_flag	<= 1'b0									;
//end else if (can_rx_en_flag==0)
//can_rx_unen_flag	<= 'b0									;
//end always @(posedge can_clk or negedge rst_n )begin
if(rst_n==1'b0) begin
can_continuity_data			<= 5'b11111								;
can_continuity_data_flag	<= 'b0									;
end else if ((one_bit_cont==9)&&(can_rx_en_flag==1)) begin
can_continuity_data			<= {can_continuity_data[3:0],can_rx}	;
can_continuity_data_flag	<= 'b0												;
end	else if (((can_continuity_data==0)||(can_continuity_data==5'b11111))&&(one_bit_cont==10)&&(cic_en_flag==0)) begin
can_continuity_data_flag	<= 'b1									;
end else if (((can_continuity_data==0)||(can_continuity_data==5'b11111))&&(one_bit_cont==10)&&(cic_en_flag==1)&&(bit_cont<14)) begin
can_continuity_data_flag	<= 'b1									;
end else if (can_rx_en_flag==0) begin
can_continuity_data			<= 5'b11111								;
can_continuity_data_flag	<= 'b0									;
end else begin
can_continuity_data_flag	<= 'b0									;
end
end  always @(posedge can_clk or negedge rst_n )begin
if(rst_n==1'b0) begin
can_rx_unen_flag	<= 'b0									;
end else if ((can_rx_en_flag==1)&&(can_continuity_data_flag==1)&&(cic_en_flag==0)) begin
can_rx_unen_flag	<= 1'b1									;
end	 else if ((can_rx_en_flag==1)&&(can_continuity_data_flag==1)&&(cic_en_flag==1)&&(bit_cont<14)) begin
can_rx_unen_flag	<= 1'b1									;
end else if (one_bit_cont==11) begin
can_rx_unen_flag	<= 1'b0									;
end else if (can_rx_en_flag==0)
can_rx_unen_flag	<= 'b0									;
end always @(posedge can_clk or negedge rst_n )begin
if(rst_n==1'b0) begin
can_id_data_cont			<= 'd10									;
end else if ((id_en_flag==1)&&(can_continuity_data_flag==1)) begin
can_id_data_cont			<= can_id_data_cont			+ 1'b1		;
end	else if (id_en_flag==0)  
can_id_data_cont			<= 'd10									;
end always @(posedge can_clk or negedge rst_n )begin
if(rst_n==1'b0) begin
can_contral_data_cont		<= 'd6									;
end else if ((contral_flag==1)&&(can_continuity_data_flag==1)) begin
can_contral_data_cont		<= can_contral_data_cont	+ 1'b1		;
end	else if (contral_flag==0) 
can_contral_data_cont		<= 'd6									;
end always @(posedge can_clk or negedge rst_n )begin
if(rst_n==1'b0) begin
can_data_data_cont			<= 'd63									;
end else if ((data_en_flag==1)&&(can_continuity_data_flag==1)) begin
can_data_data_cont			<= can_data_data_cont		+ 1'b1		;
end	else if (data_en_flag==0)  
can_data_data_cont			<= 'd63									;
end always @(posedge can_clk or negedge rst_n )begin
if(rst_n==1'b0) begin
can_cic_data_cont			<= 'd15									;
end else if ((cic_en_flag==1)&&(can_continuity_data_flag==1)) begin
can_cic_data_cont			<= can_cic_data_cont		+ 1'b1		;
end	 else if (cic_en_flag==0) 
can_cic_data_cont			<= 'd15									;
end ///always @(posedge can_clk or negedge rst_n )begin
if(rst_n==1'b0) begin
can_id_out	<= 'b0										;
end else if ((one_bit_cont==9)&&(id_en_flag==1)&&(can_rx_unen_flag==0)) begin
can_id_out	<= {can_id_out[9:0],can_rx	}				;
end	
end always @(posedge can_clk or negedge rst_n )begin
if(rst_n==1'b0) begin
can_id_out_en	<= 'b0									;
end else if ((one_bit_cont==9)&&(bit_cont==can_id_data_cont)&&(id_en_flag==1)) begin
can_id_out_en	<= 1'b1									;
end	else 
can_id_out_en	<= 'b0									;
end always @(posedge can_clk or negedge rst_n )begin
if(rst_n==1'b0) begin
can_data_out	<= 'b0										;
end else if ((one_bit_cont==9)&&(data_en_flag==1)&&(can_rx_unen_flag==0)) begin
can_data_out	<= {can_data_out[62:0],can_rx	}				;
end	
end always @(posedge can_clk or negedge rst_n )begin
if(rst_n==1'b0) begin
can_data_out_en	<= 'b0									;
end else if ((bit_cont==can_data_data_cont)&&(one_bit_cont==9)&&(data_en_flag==1)) begin
can_data_out_en	<= 1'b1									;
end	else 
can_data_out_en	<= 'b0									;
end /endmodule

在完成上述代码编写后通过CAN收发器发送数据然后利用chipscop进行数据的抓取。
数据发送如下图所示:
在这里插入图片描述

对上述代码测试时抓取到数据波形如下图:
在这里插入图片描述
从图中可以看出接收了一包完整的标准数据帧。在通过CAN调试工具进行数据的发送测试时:CAN调试工具每秒发送60包,测试了一个小时,没有出现接收数据错误。
然而在实现CAN通信时在满足一般的代码编写的情况下有两点需要特别的注意:
1、CAN2.0的协议规定,连续5个显性/隐性电平后,要填充一位隐性/显性电平。
2、在can协议中将CAN_H和CAN_L的差值为高电平时定义为显性,逻辑上表示为0,为低电平时定义为隐形,逻辑上表示为1。
(有需要代码的可以复制)


http://chatgpt.dhexx.cn/article/WnHxs26X.shtml

相关文章

关于CAN通信速率设置

一、 CAN时钟周期&#xff08;Tq&#xff09;2*晶振时钟*BRP&#xff08;波特率预分频值 baudrate prescaler&#xff09; 一个CAN时间称为一个时间量子 Tq 1&#xff09;同步段&#xff08;Synchronization Segment&#xff09;&#xff1a;1个Tq&#xff0c;tSS 2&#x…

nano的CAN通信

我买的是微雪的树莓派用的SPI转CAN。现在用在jetson nano上。我看了一下俩模块的芯片用的都是一样的&#xff0c;引脚也都对得上&#xff0c;所以我就打算拿这个模块给nano做can通信。 具备CAN功能&#xff0c;使用SPI接口CAN控制器MCP2515&#xff0c;搭配收发器SN65HVD230。 …

CAN通信基础知识

CAN是Controller Area Network 的缩写&#xff08;以下称为CAN&#xff09;&#xff0c;是ISO国际标准化的串行通信协议。由德国电气商博世公司在1986 年率先提出。此后&#xff0c;CAN 通过ISO11898 及ISO11519 进行了标准化。现在在欧洲已是汽车网络的标准协议。 CAN协议经过…

CAN通信详解

本章我们将向大家介绍如何使用STM32自带的CAN控制器来实现两个开发板之间的CAN通讯&#xff0c;并将结果显示在TFTLCD模块上。本章分为如下几个部分&#xff1a; 30.1 CAN简介 30.2 硬件设计 30.3 软件设计 30.4 下载验证 30.1 CAN简介 CAN 是Controller Area Network 的…

CAN通信总结

CAN通信总结 基本介绍 ​ 1. CAN通过两条通信线&#xff08;双绞线&#xff09;产生的电压差传输数据&#xff0c;一个CAN网络里的所有节点都挂在这两条通信线上&#xff0c;使用差分信号半双工通信。 ​ 2. CAN总线是广播类型的总线。所有节点都将始终接收所有通信&#xf…

CAN 通信原理学习

文章目录 CAN通信一&#xff1a;基本概述1.1 can总线是什么1.2 can总线协议的特点1.3 can的网络通信结构1.3.11.3.2 can协议网络层次 二&#xff1a;socket can在通信网络中的应用三 一个程序 CAN通信 一&#xff1a;基本概述 1.1 can总线是什么 CAN 是 Controller Area Net…

CAN通信协议

在 CAN 协议中&#xff0c;所有的消息都以固定的格式发送。总线空闲时&#xff0c;所有与总线相连的单元都可以开始发送新消息。两个以上的单元同时开始发送消息时&#xff0c;根据标识符&#xff08;Identifier 以下称为 ID&#xff09;决定优先级。ID 并不是表示发送的目的地…

CAN通信讲解(1)——基本知识

本文注意参考了《CAN入门书》&#xff0c;源于此书图片不再特殊标注 目录 1.1 CAN总线背景1.2 CAN总线定义1.3 CAN总线信号特性1.4 CAN总线传输1.5 OSI基本参照模型和CAN总线协议 1.1 CAN总线背景 为减少汽车线束数量&#xff0c;1986年&#xff0c;博世开发出面向汽车的CAN通…

CAN通信

通讯方式 UART&#xff1a;(Universal Asynchronous Receiver Transmitter&#xff1a;通用异步收发器/异步串行通信口)&#xff0c;是一种通用的串行数据总线&#xff0c;用于异步通信&#xff0c;支持全双工。它包括了RS232、RS499、RS423、RS422和RS485等接口标准规范和总线…

CAN通信----基本原理

STM32标准库开发 文章链接&#xff1a; STM32F103标准库开发----目录 STM32F103标准库开发----CAN总线通信实验----初始化/波特率 STM32F103标准库开发----CAN总线通信实验----发送和接收 资源链接&#xff1a; 本例程已经调试成功&#xff0c;下载即可使用。 STM32F103标准库…

CAN通信详解(全)

本章我们将向大家介绍如何使用STM32自带的CAN控制器来实现两个开发板之间的CAN通讯&#xff0c;并将结果显示在TFTLCD模块上。本章分为如下几个部分&#xff1a; 30.1 CAN简介 30.2 硬件设计 30.3 软件设计 30.4 下载验证 30.1 CAN简介 CAN 是Controller Area Network 的缩…

Tomcat优化禁用AJP协议

登录tomcat 在服务状态页面中可以看到&#xff0c;默认状态下会启用AJP服务&#xff0c;并且占用8009端口。 什么是AJP呢&#xff1f; AJP&#xff08;Apache JServer Protocol&#xff09; AJPv13协议是面向包的。WEB服务器和Servlet容器通过TCP连接来交互&#xff1b;为了…

tomcat启动出现错误:Failed to destroy end point associated with ProtocolHandler[“ajp-nio-8009“](解决非常简单)

tomcat启跑不起来而且报了很多莫名其妙的错误不知道从哪里找起 启动服务器出现这个错误 console提示&#xff1a;Failed to destroy end point associated with ProtocolHandler[“ajp-nio-8009”] 直接看web.xml的url-pattern这个属性是不是哪一个少了‘/’ 或者 如果没有…

Java安全-Tomcat AJP 文件包含漏洞(CVE-2020-1938)幽灵猫漏洞复现

Tomcat AJP 文件包含漏洞&#xff08;CVE-2020-1938&#xff09; CVE-2020-1938 又名GhostCat ApacheTomcat服务器中被发现存在文件包含漏洞&#xff0c;攻击者可利用该漏洞读取或包含Tomcat 上所有 webapp 目录下的任意文件 该漏洞是一个单独的文件包含漏洞&#xff0c;依赖…

Aapache Tomcat AJP 文件包含漏洞-(CVE-2020-1938/CNVD-2020-10487)

漏洞编号 CVE-2020-1938 CNVD-2020-10487 靶机环境 Vulhub虚拟靶场 vulhub-master/tomcat/CVE-2020-1938 启动docker&#xff1a; 启动成功&#xff1a; 0x00 漏洞简介 2月20日&#xff0c;国家信息安全漏洞共享平台&#xff08;CNVD&#xff09;发布了Apache Tomcat文件包含漏…

Apache-Tomcat-Ajp漏洞测试与修复

说明 Apache Tomcat会开启AJP连接器,方便与其他Web服务器通过AJP协议进行交互。由于Tomcat本身也内含了HTTP服务器&#xff0c;因此也可以视作单独的Web服务器。此漏洞为文件包含漏洞&#xff0c;攻击者可利用该漏洞读取或包含 Tomcat 上所有 webapp 目录下的任意文件&#xf…

解决AJP漏洞操作记录

前言 最近Tomcat爆出AJP漏洞&#xff0c;升级对应版本的Tomcat是比较好的规避方法。本文将记录笔者在升级Tomcat 9.0.31时踩过的一些坑&#xff0c;以便大家能快速升级Tomcat。 本文只针对Tomcat 9.0.31版本的操作记录。 Tomcat受影响版本&#xff1a; Apache Tomcat 9.x &l…

tomcat中ajp及8009端口用处

tomcat常用于提供servlet/jsp容器服务&#xff0c;简单方便、使用高效。但是tomcat处理静态文件资源的性能不足&#xff08;应该是serviece部分&#xff09;&#xff0c;同时&#xff0c;如果用户直接与tomcat进行http的连接获取静态资源&#xff08;连接器connector部分&#…

CVE-2020-1938 :Apache Tomcat AJP 漏洞复现和分析

一、漏洞描述 Apache Tomcat是由Apache软件基金会属下Jakarta项目开发的Servlet容器.默认情况下,Apache Tomcat会开启AJP连接器,方便与其他Web服务器通过AJP协议进行交互.但Apache Tomcat在AJP协议的实现上存在漏洞,导致攻击者可以通过发送恶意的AJP请求,可以读取或者包含Web应…

网络抓包方式复现Tomcat- AJP协议文件读取/命令执行漏洞(CVE-2020-1938 / CNVD-2020-10487)

目录 测试是否安装成功​编辑 基础简介 Tomcat Connector(连接器) ​编辑Servlet(服务程序) Tomcat内部处理请求流程 文件读取漏洞 抓包复现 需要将下图中抓取到的数据包修改一下 ​编辑 替换成二进制数据的形式&#xff1a; 运行结果 ​编辑 创建脚本文件&#xf…