AndroidAsync 框架获取 Socket.IO 的 Http 返回码

概述

上周我们的服务器端除了一些小问题,某些情况下会丢失 sessionId,Socket 连接返回 500 错误。这就需要客户端判断 Socket 连接的 http 返回码,如果是 500,则刷新 token 以使服务器得到一个新的 sessionId,但 SocketIO 默认的 connect 方法是得不到 http 返回码的。那要如何得到这个返回码呢,请接着向下看。

思路

  1. AndroidAsync 内部的 SocketIO 是通过 AsyncHttpClient 进行连接的,肯定是有 http 码返回的,但是在哪里返回的,不知道。
  2. 我们用一个无效的 sessionId 连接,服务器是会返回 500 的,查看 Log 除了一个handshake error没有其他任何有效的信息。
  3. 用 Android Studio 全局搜索字符串handshake error,无结果。
  4. 用 Android Studio 全局搜索字符串handshake,我们找到了一些线索,可以看到AsyncHttpResponse,它包含 http 返回码,所以,它就是我们要的。
  5. 一路顺藤摸瓜,发现在AsyncHttpClient类中有一个executeString(AsyncHttpRequest req, final StringCallback callback)方法,而这个StringCallback接口中有一个回调方法onCompleted(Exception e, AsyncHttpResponse source, String result),终于到了我们需要的AsyncHttpResponse
  6. 继续摸瓜,发现executeString方法是有重载的,只是他的重载方法传入的StringCallbacknull
  7. 顺着executeString方法向上摸,发现它在SocketIOConnection类中的reconnect方法中被调用了,而且调用的就是那个传null的重载。
  8. 顺着reconnect向上摸,终于找到了SocketIOClient类中的connect方法,它就是我们启动 Socket 连接的地方。

修改源码

  • connect方法添加一个参数StringCallback
1
2
//SocketIOClient类
public static Future<SocketIOClient> connect(final AsyncHttpClient client, final SocketIORequest request, final ConnectCallback callback, final AsyncHttpClient.StringCallback stringCallback)
  • reconnect方法添加一个参数StringCallback
1
2
//SocketIOConnection类
void reconnect(final DependentCancellable child, AsyncHttpClient.StringCallback stringCallback)
  • reconnect方法体中,修改一行代码。
1
2
3
//原代码:Cancellable connecting = httpClient.executeString(request)
//修改为
Cancellable connecting = httpClient.executeString(request, stringCallback)
  • 因为某些方法形参列表的修改,肯定会导致某些调用这个方法的地方报错,记得修改一下就好。

使用

1
2
3
4
5
6
7
8
9
10
11
12
SocketIOClient.connect(AsyncHttpClient.getDefaultInstance(), sir, new ConnectCallback() {
@Override
public void onConnectCompleted(Exception ex, final SocketIOClient client) {
//do something
}
}, new AsyncHttpClient.StringCallback() {
@Override
public void onCompleted(Exception e, AsyncHttpResponse source, String result) {
//得到http返回码
int statusCode = source.getHeaders().getHeaders().getResponseCode();
}
});