java - 从两个 SSLSockets(客户端)获取多个流

标签 java android ssl handshake

我有一个 Android 客户端应用程序和一个普通的 Java 服务器,都使用 SSL 加密。在服务器端,我设置了 SSLServerSockets,一个用于数据,一个用于对客户端的特殊异步指令和其他。以下是 SSLServerSocket 设置的代码:

SSLServerSocket 设置:

Security.addProvider(new Provider());

System.setProperty("javax.net.ssl.keyStore", GlobalVariables.KEYSTORE_PATH);
System.setProperty("javax.net.ssl.keyStorePassword", Server.KEY_STORE_PW);

sslServerSocketfactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();

// Enable debugging to view the handshake and communication which happens between the SSLClient and the SSLServer
System.setProperty("javax.net.debug", "all");

try
{
  serverDataSocket = (SSLServerSocket) sslServerSocketfactory.createServerSocket(Server.SERVER_DATA_PORT);
  serverStatusSocket = (SSLServerSocket) sslServerSocketfactory.createServerSocket(Server.SERVER_STATUS_PORT);

  waitForClients();
}
catch (IOException e)
{
  Log.error(ServerAgent.class, "Establishing ServerSocket was not successful.", e);
}

在此之后,我在 waitForClients() 方法中等待客户端连接,您可以在此处看到:

while (serverModel.isServerRunning())
{
  try
  {
    clientDataSocket = (SSLSocket) serverDataSocket.accept();
    clientStatusSocket = (SSLSocket) serverStatusSocket.accept();

    new Thread(new Runnable()
    {

      @Override
      public void run()
      {
        Client client = new Client(clientDataSocket, clientStatusSocket, iliasSoapClient, serverModel.getTimeoutServer());

        if (client.manageHandshake())
        {
          serverModel.addClient(client);
        }
      }
    }).start();
  }
  catch (SocketException e)
  {
    Log.warn(ServerAgent.class, "Close was invoked by an external method, so now the server is shutting down...", e);
  }
  catch (IOException e)
  {
    Log.error(ServerAgent.class, "Can not get the Socket from the ServerSocket.", e);
  }
}

在客户端,我首先连接到 serverDataSocket,然后使用以下代码连接到 serverStatusSocket:

  public boolean connect()
  {
    try
    {
      dataServerSocket = (SSLSocket)sslSocketFactory.createSocket();
      dataServerSocket.setSoTimeout(10000);
      dataServerSocket.connect(new InetSocketAddress(Server.SERVER_IP, Server.SERVER_DATA_PORT), 10000);
      dataInput = new Scanner(dataServerSocket.getInputStream());
      dataOutput = new PrintWriter(dataServerSocket.getOutputStream(), true);
    }
    catch (UnknownHostException e)
    {
      Log.e(Client.class.getName(), "Cannot connect to host with IP: " + Server.SERVER_IP + " under data port: " + Server.SERVER_DATA_PORT + ".", e);
      return false;
    }
    catch (IOException e)
    {
      Log.e(Client.class.getName(), "Common IOException: Cannot connect to host with IP: " + Server.SERVER_IP + " under data port: "
          + Server.SERVER_DATA_PORT + ".", e);
      return false;
    }

    try
    {
      statusServerSocket = (SSLSocket)sslSocketFactory.createSocket();
      statusServerSocket.setSoTimeout(10000);
      statusServerSocket.connect(new InetSocketAddress(Server.SERVER_IP, Server.SERVER_STATUS_PORT), 10000);
      statusInput = new Scanner(statusServerSocket.getInputStream());
      statusOutput = new PrintWriter(statusServerSocket.getOutputStream(), true);

      return true;
    }
    catch (UnknownHostException e)
    {
      Log.e(Client.class.getName(), "Cannot connect to host with IP: " + Server.SERVER_IP + " under status port: " + Server.SERVER_STATUS_PORT + ".", e);
      return false;
    }
    catch (IOException e)
    {
      Log.e(Client.class.getName(), "Common IOException: Cannot connect to host with IP: " + Server.SERVER_IP + " under status port: "
          + Server.SERVER_STATUS_PORT + ".", e);
      return false;
    }
  }

如果我尝试从服务器检索 InputStream 作为客户端,我会得到以下异常。不知道为什么:

02-04 22:34:07.130: E/de.hska.ilias.app.client.Client(29098): Common IOException: Cannot connect to host with IP: 192.168.0.6 under data port: 51234.
02-04 22:34:07.130: E/de.hska.ilias.app.client.Client(29098): java.net.SocketTimeoutException: SSL handshake timed out
02-04 22:34:07.130: E/de.hska.ilias.app.client.Client(29098):   at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
02-04 22:34:07.130: E/de.hska.ilias.app.client.Client(29098):   at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:398)
02-04 22:34:07.130: E/de.hska.ilias.app.client.Client(29098):   at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLInputStream.<init>(OpenSSLSocketImpl.java:658)
02-04 22:34:07.130: E/de.hska.ilias.app.client.Client(29098):   at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.java:629)
02-04 22:34:07.130: E/de.hska.ilias.app.client.Client(29098):   at de.hska.ilias.app.client.Client.connect(Client.java:64)
02-04 22:34:07.130: E/de.hska.ilias.app.client.Client(29098):   at de.hska.ilias.app.client.LoginTask.doInBackground(LoginTask.java:82)
02-04 22:34:07.130: E/de.hska.ilias.app.client.Client(29098):   at de.hska.ilias.app.client.LoginTask.doInBackground(LoginTask.java:1)
02-04 22:34:07.130: E/de.hska.ilias.app.client.Client(29098):   at android.os.AsyncTask$2.call(AsyncTask.java:287)
02-04 22:34:07.130: E/de.hska.ilias.app.client.Client(29098):   at java.util.concurrent.FutureTask.run(FutureTask.java:234)
02-04 22:34:07.130: E/de.hska.ilias.app.client.Client(29098):   at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
02-04 22:34:07.130: E/de.hska.ilias.app.client.Client(29098):   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
02-04 22:34:07.130: E/de.hska.ilias.app.client.Client(29098):   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
02-04 22:34:07.130: E/de.hska.ilias.app.client.Client(29098):   at java.lang.Thread.run(Thread.java:841)
02-04 22:34:17.200: E/de.hska.ilias.app.client.Client(29098): Common IOException: Cannot connect to host with IP: 192.168.0.6 under data port: 51234.
02-04 22:34:17.200: E/de.hska.ilias.app.client.Client(29098): java.net.SocketTimeoutException: SSL handshake timed out
02-04 22:34:17.200: E/de.hska.ilias.app.client.Client(29098):   at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
02-04 22:34:17.200: E/de.hska.ilias.app.client.Client(29098):   at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:398)
02-04 22:34:17.200: E/de.hska.ilias.app.client.Client(29098):   at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLInputStream.<init>(OpenSSLSocketImpl.java:658)
02-04 22:34:17.200: E/de.hska.ilias.app.client.Client(29098):   at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.java:629)
02-04 22:34:17.200: E/de.hska.ilias.app.client.Client(29098):   at de.hska.ilias.app.client.Client.connectLocally(Client.java:109)
02-04 22:34:17.200: E/de.hska.ilias.app.client.Client(29098):   at de.hska.ilias.app.client.LoginTask.doInBackground(LoginTask.java:93)
02-04 22:34:17.200: E/de.hska.ilias.app.client.Client(29098):   at de.hska.ilias.app.client.LoginTask.doInBackground(LoginTask.java:1)
02-04 22:34:17.200: E/de.hska.ilias.app.client.Client(29098):   at android.os.AsyncTask$2.call(AsyncTask.java:287)
02-04 22:34:17.200: E/de.hska.ilias.app.client.Client(29098):   at java.util.concurrent.FutureTask.run(FutureTask.java:234)
02-04 22:34:17.200: E/de.hska.ilias.app.client.Client(29098):   at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
02-04 22:34:17.200: E/de.hska.ilias.app.client.Client(29098):   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
02-04 22:34:17.200: E/de.hska.ilias.app.client.Client(29098):   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
02-04 22:34:17.200: E/de.hska.ilias.app.client.Client(29098):   at java.lang.Thread.run(Thread.java:841)

最佳答案

SSL 握手超时。您必须查看服务器日志以了解原因,可能在 javax.net.debug=ssl,handshake 输出中。您已将读取超时设置为十秒,这无论如何都相当短,但对于握手而言尤其如此。我会先调用 startHandshake(),然后调用 setSoTimeout(), 和/或使用更长的握手超时时间。

但是除非该服务器只为一个客户端提供服务,否则整个策略都是有风险的。如果两个客户端同时连接,您就有可能将来自第二个客户端的连接视为来自第一个客户端的第二个连接,反之亦然。

关于java - 从两个 SSLSockets(客户端)获取多个流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21564205/

相关文章:

java - 将 BitSet 设置为原始类型?

java - 使用 java.util.concurrent.executors

Android 为什么会出现此错误 ENOENT (No such file or directory)

ssl - 配置 gradle jetty 插件以使用 ssl

java - GWT:Tomcat 无法序列化 'javax.net.ssl.SSLException'

java - 测试仪的类逻辑错误显示以前的时间而不是新的

java - 将字节数组转换为base64字符串java

java - Android代码读取文件异常

android - 将 Intent 从服务发送到 Activity

ssl - Jenkins 2 和 Atlassian Crowd(crowd2 插件)与双向 SSL 集成