使用OkHttp覆盖SocketFactory后的问题

时间:2015-01-14 16:13:51

标签: android ssl okhttp

在将我的应用程序更新为api 21之后,我遇到了使用https请求的麻烦。经过深入的代码审查后,我发现了一个有趣的错误。

我的应用程序现在已经用api-21编译了,这个api在sdk 2.2.0版本中有一个新版本的okHttp。旧版本的应用程序使用了okHttp 2.0.0的版本。

对于2.2.0版本,当我尝试打开新的https请求时,我有一个例外。例外是:

java.net.SocketException: Unconnected sockets not implemented
        at javax.net.SocketFactory.createSocket(SocketFactory.java:64)
        at com.squareup.okhttp.Connection.connect(Connection.java:144)
        at com.squareup.okhttp.Connection.connectAndSetOwner(Connection.java:169)
        at com.squareup.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:119)
        at com.squareup.okhttp.internal.http.RouteSelector.next(RouteSelector.java:134)
        at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:314)
        at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:237)
        at com.squareup.okhttp.Call.getResponse(Call.java:233)
        at com.squareup.okhttp.Call.execute(Call.java:84) 

问题是okHttp改变了Connection类在2.1.0版上的工作方式。在版本2.0.0上,连接直接创建一个新的普通Socket,但知道请求此套接字到套接字工厂,此套接字将升级到TLS。改变是:

socket = route.address.socketFactory.createSocket();

我的问题是我已经为NotHttpSocketFactory覆盖了socketFactory,并且这个实现什么都不做(没关系,你想删除http连接)和方法createSocket()没有被覆盖。我不喜欢允许http请求。

我重写了SocketFactory。

client.setSocketFactory(new BlackphoneStubSocketFactory());

我不明白为什么我需要一个普通的套接字,因为我正在创建一个https请求。这有必要吗?我可以覆盖方法createSocket()并返回一个空套接字,但这是必要的,或者它是OkHttp上的一个错误。

2 个答案:

答案 0 :(得分:1)

确保在自定义工厂中定义createSocket()。

val httpClient = OkHttpClient.Builder()
    .connectTimeout(5, TimeUnit.SECONDS)
    .retryOnConnectionFailure(false)
    .socketFactory(object: SocketFactory() {
        val factory = SocketFactory.getDefault()

        override fun createSocket(): Socket {
            return wrap(factory.createSocket())
        }

        override fun createSocket(p0: String?, p1: Int): Socket {
            return wrap(factory.createSocket(p0, p1))
        }

        override fun createSocket(p0: InetAddress?, p1: Int): Socket {
            return wrap(factory.createSocket(p0, p1))
        }

        override fun createSocket(p0: String?, p1: Int, p2: InetAddress?, p3: Int): Socket {
            return wrap(factory.createSocket(p0, p1, p2, p3))
        }

        override fun createSocket(p0: InetAddress?, p1: Int, p2: InetAddress?, p3: Int): Socket {
            return wrap(factory.createSocket(p0, p1, p2, p3))
        }

        private fun wrap(s: Socket): Socket {
            s.receiveBufferSize = 32*1024*1024
            return s
        }
    })
    .build()

答案 1 :(得分:0)

如果您想使用OkHttp 2.2执行此操作,请使用ConnectionSpec禁用纯文本连接。例如:

client.setConnectionSpecs(Collections.singletonList(ConnectionSpec.MODERN_TLS));  

这将删除对明文连接的支持,以及TLS后备。