最近项目上需要和一家银行做银企互联相关的工作,碰到个非常怪异的问题,连续两次发送http post请求,第一次请求正常,第二次请求银行系统阻塞一直无响应,一直等到我方客户端设置的超时时间,造成请求失败。
由于对方文档没有给出特别详细的说明,对方使用的http协议的版本(1.0 or 1.1)、是否支持持久连接等问题都不是很清楚,然后是进行了各种尝试,我方客户端默认使用持久连接,然后改为短连接后仍然无效。在网上查了下http1.o 和http1.1协议的区别(Key Differences between HTTP/1.0 and HTTP/1.1),主要区别是否支持持久连接,增加了http header的方法类型等,认为这个地方关系应该不大。最后实在没有办法了,上抓包工具看看吧,在wrieshark下出现问题的抓包如下:
根据我们掌握的TCP封包表头状态码含义:
o URG(Urgent):若为 1 则代表该封包为紧急封包, 接收端应该要紧急处理,且图十二当中的 Urgent Pointer 字段也会被启用。
o ACK(Acknowledge):若为 1 代表这个封包为响应封包, 则与上面提到的 Acknowledge Number 有关。
o PSH(Push function):若为 1 时, 代表要求对方立即传送缓冲区内的其它对应封包,而无须等待缓冲区满了才送。
o RST(Reset):如果 RST 为 1 的时候, 表示联机会被马上结束,而无需等待终止确认手续。这也就是说,这是个强制结束的联机, 且发送端已断线。
o SYN(Synchronous):若为 1 , 表示发送端希望双方建立同步处理,也就是要求建立联机。通常带有 SYN 标志的封包表示『主动』要连接到对方的意思。
o FIN(Finish):若为 1 ,表示传送结束, 所以通知对方数据传毕,是否同意断线,只是发送者还在等待对方的响应而已。
不论是服务器端还是客户端,都必须要透过一次 SYN 与 ACK 来建立联机总共会进行三次的握手!
由此大致分析了下,貌似客户端再次请求的时候没有进行SYN(尝试连接的请求,难道用的还是一个连接吗?)
接下来检查代码,看看有没有用到连接缓存或没有连接端口的情况(HttpUrlConnection.close等),结果均没有发现类似的问题。并且此处的HTTP通信连接代码是基类复用代码,在其他银行的直连中均没有发现类似的问题。
问题到底在哪嗯?
最后我设想使用传输层协议(TCP)的APISocket实现发送Http请求的功能,看看是不是由于应用层程序之间服务器和客户端HTTP连接关闭的某些冲突引起的此类问题,另一方面,从经验上来看,以前使用的Socket连接的方式还是稳定的。
接下来的就是具体的实现了,就不在此堆砌代码了,具体可以参考StackOverflow上面的一个问答帖子Send HTTP Request manually via socket。
最终我想你已经猜到了,这种方式是可以的。但是还是本文中的提出的问题,那些通信连接冲突到底是什么呢?
再想想.........