【问题标题】:Getting multiple streams from two SSLSockets (Client side)从两个 SSLSocket 获取多个流(客户端)
【发布时间】:2014-02-04 21:47:37
【问题描述】:

我有一个 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)

【问题讨论】:

    标签: java android ssl handshake


    【解决方案1】:

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

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

    【讨论】:

    • 你能举个例子,如何为一个客户端保存多个异步流吗?
    • 问题不在于超时。我正在局域网中测试它。问题是,如果我只用一个套接字尝试它,它工作正常(SSL 握手),但如果我像上面提到的那样做,它会打印出上面的消息。我需要为两个套接字生成两个证书还是一个就足够了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-18
    • 2011-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-30
    • 2016-11-11
    相关资源
    最近更新 更多