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

时间:2014-02-04 21:47:38

标签: 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)

1 个答案:

答案 0 :(得分:0)

SSL握手超时。你必须查看服务器日志,看看为什么,可能在javax.net.debug = ssl,握手输出。您已将读取超时设置为十秒,无论如何这都是相当短的,但尤其是握手。我先调用startHandshake(),然后调用setSoTimeout(),和/或使用更长的超时进行握手。

除非此服务器只为一个客户端提供服务,否则整个策略都存在风险。如果两个客户端同时连接,则存在将来自第二个客户端的连接视为来自第一个客户端的第二个连接的危险,反之亦然。