无法使套接字无阻塞

时间:2010-12-20 07:53:29

标签: android https

人。   我想让我的应用程序支持https连接。我的HttpClient代码如下:

        HttpParams params = new BasicHttpParams();
        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_0);
        HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
        HttpProtocolParams.setUseExpectContinue(params, true);
        HttpConnectionParams.setConnectionTimeout(params, SO_TIMEOUT);
        HttpConnectionParams.setSoTimeout(params, SO_TIMEOUT);
        HttpConnectionParams.setSocketBufferSize(params, DEFAULT_BUFFER_SIZE);

    SchemeRegistry schReg = new SchemeRegistry();
    schReg.register(new Scheme("http", PlainSocketFactory
            .getSocketFactory(), HTTP_PORT));
    schReg.register(new Scheme("https", new CustomSSLSocketFactory(),
            HTTPS_PORT));
    ClientConnectionManager connMgr = new ThreadSafeClientConnManager(params, schReg);              

    PersistentCookieStore store = new PersistentCookieStore();
    store.clearExpired(new Date());
    client = new DefaultHttpClient(connMgr, params);

    client.setCookieStore(store);

    client.addRequestInterceptor(new HttpRequestInterceptor() {
        public void process(HttpRequest request, HttpContext context) {
            // Add header to accept gzip content
            if (!request.containsHeader(HEADER_ACCEPT_ENCODING)) {
                request.addHeader(HEADER_ACCEPT_ENCODING, ENCODING_GZIP);
            }
        }
    });
    client.addResponseInterceptor(new HttpResponseInterceptor() {
        public void process(HttpResponse response, HttpContext context) {
            // Inflate any responses compressed with gzip
            final HttpEntity entity = response.getEntity();

            if(entity != null){
                final Header encoding = entity.getContentEncoding();
                if (encoding != null) {
                    for (HeaderElement element : encoding.getElements()) {
                        if (element.getName().equalsIgnoreCase(ENCODING_GZIP)) {
                            response.setEntity(new InflatingEntity(response
                                    .getEntity()));
                            break;
                        }
                    }
                }
            }

        }
    });
    requests = new ArrayList<HttpUriRequest>();
}*

但它会在logcat中出现异常:

*12-20 07:42:41.895: DEBUG/com.ceosoft.alumlife.http.HttpClient(504): GET https://174.129.95.184:8443/AlumniFinderServer/ws/event/all
12-20 07:42:42.125: WARN/SingleClientConnManager(504): Invalid use of SingleClientConnManager: connection still allocated.
12-20 07:42:42.125: WARN/SingleClientConnManager(504): Make sure to release the connection before allocating another one.
12-20 07:42:42.134: WARN/SingleClientConnManager(504): Invalid use of SingleClientConnManager: connection still allocated.
12-20 07:42:42.134: WARN/SingleClientConnManager(504): Make sure to release the connection before allocating another one.
12-20 07:42:42.144: INFO/System.out(504): cookies  == None
12-20 07:42:42.164: WARN/SingleClientConnManager(504): Invalid use of SingleClientConnManager: connection still allocated.
12-20 07:42:42.164: WARN/SingleClientConnManager(504): Make sure to release the connection before allocating another one.
12-20 07:42:42.239: WARN/SingleClientConnManager(504): Invalid use of SingleClientConnManager: connection still allocated.
12-20 07:42:42.239: WARN/SingleClientConnManager(504): Make sure to release the connection before allocating another one.
12-20 07:42:54.734: INFO/System.out(504): IOException e
 java.io.IOException: Unable to make socket non blocking
     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.nativeconnect(Native Method)
     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:316)
     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLInputStream.<init>(OpenSSLSocketImpl.java:520)
     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.java:461)
     at org.apache.http.impl.io.SocketInputBuffer.<init>(SocketInputBuffer.java:93)
     at org.apache.http.impl.SocketHttpClientConnection.createSessionInputBuffer(SocketHttpClientConnection.java:83)
     at org.apache.http.impl.conn.DefaultClientConnection.createSessionInputBuffer(DefaultClientConnection.java:170)
     at org.apache.http.impl.SocketHttpClientConnection.bind(SocketHttpClientConnection.java:106)
     at org.apache.http.impl.conn.DefaultClientConnection.openCompleted(DefaultClientConnection.java:129)
     at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:171)
     at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
     at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
     at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:348)
     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
     at com.ceosoft.alumlife.http.HttpClient.getResponse(HttpClient.java:440)
     at com.ceosoft.alumlife.http.HttpClient.getPublicData(HttpClient.java:317)
     at com.ceosoft.alumlife.http.Client.getEventList(Client.java:423)
     at com.ceosoft.alumlife.data.manager.DataManager$8.launch(DataManager.java:330)
     at com.ceosoft.alumlife.data.DataTask.doInBackground(DataTask.java:93)
     at com.ceosoft.alumlife.data.DataTask.doInBackground(DataTask.java:1)
     at android.os.AsyncTask$2.call(AsyncTask.java:185)
     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
     at java.util.concurrent.FutureTask.run(FutureTask.java:137)
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
     at java.lang.Thread.run(Thread.java:1096)*

_ --------------------------------------- --------------------- CustomSSLSocketFactory.java:

import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.net.UnknownHostException; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException;

import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocket; import javax.net.ssl.TrustManager;

import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.conn.scheme.LayeredSocketFactory; import org.apache.http.conn.scheme.SocketFactory; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams;

/ **  *工厂用于创建ssl套接字并接受自己  * 证书  * / 公共类CustomSSLSocketFactory实现了SocketFactory,                                     LayeredSocketFactory {

private static final String SSL_PROTOCOL_NAME = "TLS";
private SSLContext sslContext = null;

/**
 * Creates a new CustomSSLSocket object.
 * 
 * @return the SSL context
 * @throws NoSuchAlgorithmException
 *             the no such algorithm exception
 * @throws KeyManagementException
 *             the key management exception
 * @throws KeyStoreException
 *             the key store exception
 */
private static SSLContext createSSLContext() throws 
                        NoSuchAlgorithmException, 
                        KeyManagementException, 
                        KeyStoreException {
    SSLContext context = SSLContext.getInstance(SSL_PROTOCOL_NAME);

    context.init(null, new TrustManager[] { new MyTrustManager() }, null);
    //context.init(null, new TrustManager[] { new CustomX509TrustManager(null) }, new SecureRandom());
    return context;
}


/**
 * Gets the SSL context. Create new context and handle exceptions. 
 * 
 * @return the sSL context
 * @throws IOException
 *             Signals that an I/O exception has occurred.
 */
private SSLContext getSSLContext() throws IOException {
    if (sslContext == null) {
        try {
            sslContext = createSSLContext();
        } catch (KeyManagementException e) {
            throw new IOException(e.getLocalizedMessage());
        } catch (NoSuchAlgorithmException e) {
            throw new IOException(e.getLocalizedMessage());
        } catch (KeyStoreException e) {
            throw new IOException(e.getLocalizedMessage());
        }
    }
    return sslContext;
}

/* (non-Javadoc)
 * @see org.apache.http.conn.scheme.SocketFactory#createSocket()
 */
public Socket createSocket() throws IOException {

    return getSSLContext().getSocketFactory().createSocket();
}

/* (non-Javadoc)
 * @see org.apache.http.conn.scheme.SocketFactory#isSecure(java.net.Socket)
 */
public boolean isSecure(Socket socket) throws IllegalArgumentException {
    return true;
}


/* (non-Javadoc)
 * @see org.apache.http.conn.scheme.LayeredSocketFactory#
 * createSocket(java.net.Socket, java.lang.String, int, boolean)
 */
public Socket createSocket(Socket socket, String host, int port,
        boolean autoClose) throws IOException, UnknownHostException {

    return getSSLContext().getSocketFactory().createSocket();
}

/* (non-Javadoc)
 * @see org.apache.http.conn.scheme.SocketFactory#
 * connectSocket(java.net.Socket, java.lang.String, int, 
 * java.net.InetAddress, int, org.apache.http.params.HttpParams)
 */
@Override
public Socket connectSocket(Socket socket, String reqHost, int reqPort,
        InetAddress arg3, int arg4, HttpParams params) throws IOException,
        UnknownHostException, ConnectTimeoutException {

    int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
    int soTimeout = HttpConnectionParams.getSoTimeout(params);

    InetSocketAddress remoteAddress = new InetSocketAddress(reqHost, reqPort);
    SSLSocket sslSocket = null;
    if (socket != null) {
        sslSocket = (SSLSocket) socket;
    } else {
        sslSocket = (SSLSocket) createSocket();
    }
    InetSocketAddress inetSocketAddress = new InetSocketAddress(arg3, arg4);
    sslSocket.bind(inetSocketAddress);

    sslSocket.connect(remoteAddress, connTimeout);
    sslSocket.setSoTimeout(soTimeout);
    return sslSocket;
}

}


import java.security.cert.CertificateException; import java.security.cert.X509Certificate;

导入javax.net.ssl.X509TrustManager;

/ **  *  * @file MyTrustManager.java  * @author Samuel.Cai  * @date 2010-12-21  * / 公共类MyTrustManager实现X509TrustManager {

@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
        throws CertificateException {
    // TODO Auto-generated method stub

}

@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
        throws CertificateException {
    // TODO Auto-generated method stub

}

@Override
public X509Certificate[] getAcceptedIssuers() {
    // TODO Auto-generated method stub
    return null;
}

}

1 个答案:

答案 0 :(得分:1)

当我进行独立演示时,请使用这些代码。 (更少的代码和删除不相关的代码,可能会导致一些非常有价值的信息)

真正有价值的信息如下:

12-23 01:19:38.618:ERROR / NativeCrypto(265):连接期间出现未知错误5   java.io.IOException:SSL握手失败:系统调用期间的I / O错误,管道损坏      在org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.nativeconnect(本机方法)      在org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:316)      在org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl $ SSLInputStream。(OpenSSLSocketImpl.java:520)      在org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.java:461)      在org.apache.http.impl.io.SocketInputBuffer。(SocketInputBuffer.java:93)      at org.apache.http.impl.SocketHttpClientConnection.createSessionInputBuffer(SocketHttpClientConnection.java:83)      at org.apache.http.impl.conn.DefaultClientConnection.createSessionInputBuffer(DefaultClientConnection.java:170)      在org.apache.http.impl.SocketHttpClientConnection.bind(SocketHttpClientConnection.java:106)      at org.apache.http.impl.conn.DefaultClientConnection.openCompleted(DefaultClientConnection.java:129)      at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:171)      在org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)      在org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)      在org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:348)      在org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)      在org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)      在org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)      在info.iamkebo.demo.Demo.GetHttps(Demo.java:75)      在info.iamkebo.demo.Demo.onCreate(Demo.java:40)      在android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)      在android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)      在android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)      在android.app.ActivityThread.access $ 2300(ActivityThread.java:125)      在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:2033)


然后我从以下方面得到解决方案:

Custom SSL handling stopped working on Android 2.2 FroYo

再次感谢Eric。