AJP协议总结与分析

AJP 协议是面向包的协议,采用二进制形式代替文本形式,以提高性能。 Web Server 一般维持和 Web Container 的多个 TCP Connecions ,即 TCP 连接池,多个 request/respons 循环重用同一个 Connection 。但是当 Connection 被分配( Assigned )到某个请求时,该请求完成之前,其他请求不得使用该连接。

Tcp Connection 具有两种状态:

(1). Idle

没有请求正使用该连接。

(2). Assigned

当前连接正在处理某个请求 .

 

数据类型 :

  AJP 协议中包括四种数据类型: Byte, Boolean , Integer and String .

  Byte: 一个字节

    Boolean 一个字节, 1 = true, 0 = false

  Integer :两个字节,无符号整数,高位字节在前。

  String: 可变字符串,最大长度为 2^16. 字符串的前而会有二个字节( Integer 型)表示字符串的长度, -1 表示 null 。字符串后面会跟上 终结符 ”\0” ,而且字符串长度不包括这个终结符。

 

AJP 的包结构 , 图表 1

包方向

0

1

2

3

4…(n+3)

Server->Container

0x12

0x34

数据长度 (n)

数据 (payload)

Container->Server

A

B

数据长度 (n)

数据 (payload)

                       图表 1

可以看出,从 apache 发向 tomcat 包都带有 0x1234 头,而从 tomcat 发向 apache 的包都带有 AB(ascii ) 头,随后二字节代表数据的长度(不包括前四个字节) . 所认 AJP 包的最大长度可以接近 2^16 ,但目前的版本支持的最大包长度为 2^13 ,即 8K

 

再看数据部分 (payload), Server->Container 的请求体包外,其他包的数据部分的首字节为其消息类型 (code) ,如下表(描述部分是原文,译成中文本人认为更难理解,英文表义比中文是好一些) :

方向

code

包类型

描述

Server->Container

2

Forward Request

Begin the request-processing cycle with the following data

7

Shutdown

The web server asks the container to shut itself down

8

Ping

The web server asks the container to take control (secure login phase).

10

Cping

The web server asks the container to respond quickly with a CPong

none

Data

Size (2 bytes) and corresponding body data.

Container->Server

3

Send Body Chunk

Send a chunk of the body from the servlet container to the web server

4

Send Headers

Send the response headers from the servlet container to the web server

5

End Response

Marks the end of the response

6

Get Body Chunk

Get further data from the request if it hasn't all been transferred yet

9

CPong Reply

The reply to a CPing request

Forward Request 包数据部分( payload )结构:

AJP13_FORWARD_REQUEST :=

    prefix_code      (byte) 0x02 = JK_AJP13_FORWARD_REQUEST

    method           (byte)

    protocol         (string)

    req_uri          (string)

    remote_addr      (string)

    remote_host      (string)

    server_name      (string)

    server_port      (integer)

    is_ssl           (boolean)

    num_headers      (integer)

    request_headers *(req_header_name req_header_value)

    attributes      *(attribut_name attribute_value)

request_terminator (byte) OxFF

---------------------------------------------------------------------------------------------------------------------------------

req_header_name :=

sc_req_header_name | (string)  [see below for how this is parsed]

---------------------------------------------------------------------------------------------------------------------------------

 

sc_req_header_name := 0xA0xx (integer)

req_header_value := (string)

---------------------------------------------------------------------------------------------------------------------------------

attribute_name := sc_a_name | (sc_a_req_attribute string)

attribute_value := (string)

 

(1)     prefix_code 所有的 Forward Request 包都是 0x02.

(2)     Method: 一个字节,对方法的编码,其对应如下(只列了部分):

Command Name

code

POST      

4

OPTIONS 

1

PUT       

5

GET     

2

DELETE    

6

HEAD    

3

TRACE     

7

( 参考: http://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html)

 

(3)     protocol, req_uri, remote_addr, remote_host, server_name, server_port, is_ssl : 每个请求包都有这几个字段,格式都是 长度+字符串值 +\0 结束符。

(4)     num_headers: 请求头的个数,两个字节。

(5)     request_headers:

请求头名称分化为两类, 一类请求头被转换为 0xA0xx 格式(如下表所示),其他请求头仍然用原字符串编码。

 

 

请求头

Code

Code 名称

accept

0xA001

SC_REQ_ACCEPT

accept-charset

0xA002

SC_REQ_ACCEPT_CHARSET

accept-encoding

0xA003

SC_REQ_ACCEPT_ENCODING

accept-language

0xA004

SC_REQ_ACCEPT_LANGUAGE

authorization

0xA005

SC_REQ_AUTHORIZATION

connection

0xA006

SC_REQ_CONNECTION

content-type

0xA007

SC_REQ_CONTENT_TYPE

content-length

0xA008

SC_REQ_CONTENT_LENGTH

cookie

0xA009

SC_REQ_COOKIE

cookie2

0xA00A

SC_REQ_COOKIE2

host

0xA00B

SC_REQ_HOST 0xA00C

pragma

0xA00C

SC_REQ_PRAGMA

referer

0xA00D

SC_REQ_REFERER

user-agent

0xA00E

SC_REQ_USER_AGENT

(6)     Java 代码读取头两个字节的整数型,如果高位字节为 ”0xA0” ,则第二字节为上在列表的索引。如果高位字节不是 ”0xA0” ,则这两个字节为随后请求头名称的长度。

(7)     Attributes :很少用,直接看 tomcat 文档吧。      

(8)     request_terminator: 一个字节 0xFF, 请求结束符。

 

响应包数据部分 (payload) 结构 :

AJP13_SEND_HEADERS :=

  prefix_code       4

  http_status_code  (integer)

  http_status_msg   (string)

  num_headers       (integer)

  response_headers *(res_header_name header_value)

 

res_header_name :=

    sc_res_header_name | (string)   [see below for how this is parsed]

 

sc_res_header_name := 0xA0 (byte)

header_value := (string)

 

AJP13_SEND_BODY_CHUNK :=

  prefix_code   3

  chunk_length  (integer)

  chunk        *(byte)

 

AJP13_END_RESPONSE :=

  prefix_code       5

  reuse             (boolean)

 

AJP13_GET_BODY_CHUNK :=

  prefix_code       6

  requested_length  (integer)

 

1.       response_headers: 和请求头一样,一类响应头被转换为 0xA0xx 格式(如下表所示),其他响应头名称采用原字符串编码。

请求头

Code

Code 名称

Content-Type

0xA001

SC_RESP_CONTENT_TYPE

Content-Language

0xA002

SC_RESP_CONTENT_LANGUAGE

Content-Length

0xA003

SC_RESP_CONTENT_LENGTH

Date

0xA004

SC_RESP_DATE

Last-Modified

0xA005

SC_RESP_LAST_MODIFIED

Location

0xA006

SC_RESP_LOCATION

Set-Cookie

0xA007

SC_RESP_SET_COOKIE

Set-Cookie2

0xA008

SC_RESP_SET_COOKIE2

Servlet-Engine

0xA009

SC_RESP_SERVLET_ENGINE

Status

0xA00A

SC_RESP_STATUS

WWW-Authenticate

0xA00B

SC_RESP_WWW_AUTHENTICATE

2.       reuse: 如果为 1, 表示该连接可以被子重用,否则这个连接应该关闭。

 

下面我们来看一个简单 AJP 请求过程中抓到的请求包:

http://localhost/test/testCluster.jsp 请求:

AJP协议总结与分析

 

1 2 字节是上文所说的 Server->Container 包头, 3 4 字节表示包长度 (0x01b0=432), 即从第 5 个字节到最后的一个字节( ff )的长度。第 5 个字节( 02 )代表是 ”Forward Request” 包。

6 个字节 (02) 代表是 Get 请求。第 7 8 字节 (0x0008) 代表 protocol 字符串的长度,后 8 个字节为 protocol 字符串 (HTTP/1.1), 9 个字节为 protocol 字符串的终结符“ \0 ”。

18-41 字节 代表 req_uri 字符串 (0x15+2+1=24 )

42-53 字节代表 remote_addr 字符串 (0x09+2+1=12 )

54-55 两字节 (0xffff=-1) 代表 null 字符串 , remote_host 不存在。

56-67 两字节 代表 server_name 字符串 (0x09+2+1=12 )

68-69 两字节 (0x0050=80) 代表 server_port

70 字节 (0x00) 代表 is_ssl false

71-72 两字节 (0x0009) 代表该请求有 9 个请求头 , 如图中的前 9 个红色 椭圆 .

10 个红色椭圆 (0x06) 代表 Attributes route.

11 个红椭圆之后,代表 AJP_REMOTE_PORT JK_LB_ACTIVATION 两个请求属性 .

最后一个字节 0xFF 表示请求结束。

 
响应头数据包:

AJP协议总结与分析

和请示头比较类似,不再细描述。其中第 5 个字节 0x04 代表 ”Send Headers” 响应。

并且没有终结符字节 0xFF.

 

响应正文数据包
:

AJP协议总结与分析

 

响应结束 End Response:

其中最后一个字节 (01) ,代表当前连接仍然可用。

(完)

你可能感兴趣的:(总结)