今天在Server发现一个错误日志:
写道
ParseException#Not a valid protocol version: ""HTTP/1.1 201 Created#org.apache.http.ParseException: Not a valid protocol version: ""HTTP/1.1 201 Created
org.apache.http.message.BasicLineParser.parseProtocolVersion(BasicLineParser.java:147)
org.apache.http.message.BasicLineParser.parseStatusLine(BasicLineParser.java:365)
org.apache.http.impl.nio.codecs.DefaultHttpResponseParser.createMessage(DefaultHttpResponseParser.java:114)
org.apache.http.impl.nio.codecs.DefaultHttpResponseParser.createMessage(DefaultHttpResponseParser.java:51)
org.apache.http.message.BasicLineParser.parseProtocolVersion(BasicLineParser.java:147)
org.apache.http.message.BasicLineParser.parseStatusLine(BasicLineParser.java:365)
org.apache.http.impl.nio.codecs.DefaultHttpResponseParser.createMessage(DefaultHttpResponseParser.java:114)
org.apache.http.impl.nio.codecs.DefaultHttpResponseParser.createMessage(DefaultHttpResponseParser.java:51)
找到对应的代码:
public ProtocolVersion parseProtocolVersion(final CharArrayBuffer buffer, final ParserCursor cursor) throws ParseException { Args.notNull(buffer, "Char array buffer"); Args.notNull(cursor, "Parser cursor"); final String protoname = this.protocol.getProtocol(); final int protolength = protoname.length(); final int indexFrom = cursor.getPos(); final int indexTo = cursor.getUpperBound(); skipWhitespace(buffer, cursor); int i = cursor.getPos(); // long enough for "HTTP/1.1"? if (i + protolength + 4 > indexTo) { throw new ParseException ("Not a valid protocol version: " + buffer.substring(indexFrom, indexTo)); } // check the protocol name and slash boolean ok = true; for (int j=0; ok && (j<protolength); j++) { ok = (buffer.charAt(i+j) == protoname.charAt(j)); } if (ok) { ok = (buffer.charAt(i+protolength) == '/'); } if (!ok) { throw new ParseException ("Not a valid protocol version: " + buffer.substring(indexFrom, indexTo)); }
说明协议栈在读取buffer.substring(indexFrom, indexTo)的时候读到的是""HTTP/1.1 201 Created,前面有两个双引号。抓包发现,在同一个长连接上出现这种情况:
写道
GET /check HTTP/1.1
Host: abc.com
Connection: keep-alive
Cache-Control: max-age=0
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
HTTP/1.1 204 OK
Date: Sat, 12 Nov 2016 04:41:29 GMT
Content-Length: 2
""Get /creat HTTP/1.1
Host: abc.com
Connection: keep-alive
Cache-Control: max-age=0
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
HTTP/1.1 201 Created
Date: Sat, 12 Nov 2016 04:41:29 GMT
Content-Length: 2
...
Host: abc.com
Connection: keep-alive
Cache-Control: max-age=0
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
HTTP/1.1 204 OK
Date: Sat, 12 Nov 2016 04:41:29 GMT
Content-Length: 2
""Get /creat HTTP/1.1
Host: abc.com
Connection: keep-alive
Cache-Control: max-age=0
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
HTTP/1.1 201 Created
Date: Sat, 12 Nov 2016 04:41:29 GMT
Content-Length: 2
...
大家注意我标红的这个应答,返回的是204,却标明了Content-Length: 2,这个应答是不符合HTTP协议定义的:
https://tools.ietf.org/html/rfc7230#section-3.3.1
3.3.3. Message Body Length
The length of a message body is determined by one of the following (in order of precedence): 1. Any response to a HEAD request and any response with a 1xx (Informational), 204 (No Content), or 304 (Not Modified) status code is always terminated by the first empty line after the header fields, regardless of the header fields present in the message, and thus cannot contain a message body.
问题定位:
在一条长连接上返回的两个应答中,第一个应答返回的应答码是204,却在body中带了两个引号,违反了HTTP1.1的规范,导致遵守了该规范的Apache的读取第一个应答的线程没有从流中读出最后两个引号,而读取第二个应答的时候发现前两个字节是两个双引号,不是HTTP/1.1,直接抛出异常。
结论,204的应答一定要遵守规范,不能再body中写数据,否则会污染流中的数据,影响长连接上对下个数据包的读取。
相关推荐
在Java中实现接口协议的通信主要依赖于Socket编程,其中可能涉及到使用Java的内置库和框架,例如JAXP(Java API for XML Processing)用于解析和生成XML文档,以及Apache HttpClient等第三方库用于构建HTTP请求和...
### 计算机网络实验指导书关键知识点解析 #### 双绞线的制作与测试 - **实验目的**: - 熟练掌握网线制作专用工具的应用。 - 深入理解网络硬件组成部分及其相互关系。 - 掌握直通线和交叉线的制作方法。 - ...
- **应用场景:** Message-Driven Beans通常用于接收JMS消息并触发相应的业务逻辑处理。 **4. JTA (Java Transaction API):** - **定义:** JTA是Java平台提供的用于协调分布式事务的标准API。 - **与JMS的关系:** ...
嵌入式系统开发_STM32微控制器_ESP8266WiFi模块_心率传感器_加速度计_OLED显示屏_蓝牙40_低功耗设计_实时操作系统_智能手表_多功能健康监测_运动数据记录_
驾校自动化_网页自动化爬虫技术_Python27多线程HTTP请求模拟_龙泉驾校2014版约车系统自动预约助手_通过模拟登录和循环请求实现自动约车功能_支持失败自动递增车号重试_
Linux系统编程_操作系统内核_系统调用_进程线程_信号处理_文件IO_进程间通信_多线程同步_网络编程_UNIX环境编程_中文翻译勘误_错误修正_代码示例优化_技术文档校对_开
wanjunshe_Python-Tensorflow_12888_1745868924470
scratch少儿编程逻辑思维游戏源码-铅笔画.zip
即时通讯应用开发_基于LeanCloud云服务与Android原生开发_集成QQ第三方登录与即时聊天功能的社交应用_实现用户注册登录创建聊天室发送文字消息展示用户信息头像昵称并提供
scratch少儿编程逻辑思维游戏源码-伞兵大乱斗(云变量).zip
scratch少儿编程逻辑思维游戏源码-楼层酷跑.zip
scratch少儿编程逻辑思维游戏源码-零下之寒颤.zip
scratch少儿编程逻辑思维游戏源码-密室逃生.zip
少儿编程scratch项目源代码文件案例素材-爪猫足球.zip
命令行完成git本地仓库创建、将代码提交到暂存区、查看暂存区信息、将代码提交到本地仓库、将本地仓库关联到远程仓库、推送到远程仓库全过程的截图
少儿编程scratch项目源代码文件案例素材-纸.zip
scratch少儿编程逻辑思维游戏源码-日本冒险.zip
scratch少儿编程逻辑思维游戏源码-狼人杀跑酷.zip
scratch少儿编程逻辑思维游戏源码-史莱姆杀手.zip
少儿编程scratch项目源代码文件案例素材-粘粘世界.zip