SSL套接字OutputStream仅在Windows上写入速度慢

时间:2013-03-28 08:52:33

标签: java windows ssl

服务器: Linux

经过测试的客户端:OS X,CentOS,Windows

服务器/客户端编程语言 Java

Server-side

SSLServerSocketFactory sslserversocketfactory =
                (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket sslserversocket =
                (SSLServerSocket) sslserversocketfactory.createServerSocket(9999);
SSLSocket sslsocket = (SSLSocket) sslserversocket.accept();

InputStream inputstream = sslsocket.getInputStream();
InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
BufferedReader bufferedreader = new BufferedReader(inputstreamreader);

String string = null;
while ((string = bufferedreader.readLine()) != null) {
    System.out.println(string);
    System.out.flush();
}

使用此选项执行的服务器程序

-Djavax.net.ssl.keyStore=mySrvKeystore -Djavax.net.ssl.keyStorePassword=123456

证书:在Linux上使用keytool创建

keytool -genkey -keystore mySrvKeystore -keyalg RSA

客户端

....
    SocketAddress sa = new InetSocketAddress(ip, port);
....
    SSLContext sslContext = SSLContext.getInstance("SSL");
....
      sslContext.init(.........., new SecureRandom());

      SSLSocketFactory socketFactory = sslContext.getSocketFactory();
      this.clientSock = socketFactory.createSocket();
      this.clientSock.connect(sa, this.ConnectTimeout);       
      this.clientSock.setSoTimeout(this.RecvTimeout);
      this.clientSock.setReuseAddress(true);
....

public boolean writeTo(String procname, BufferedOutputStream out, byte[] data)
{....
    out.write(data, 0, data.length);
    out.flush();
....}

结果:一切都运行良好,但只有来自Windows的客户端程序,写入输出流时会延迟。

  1. SSL套接字连接
  2. 设置输出/输入流
  3. 将数据写入输出流
  4. 冲洗
  5. ......持续4-5秒,此时没有任何理由卡在这里......

    1. 靠近
    2. 延迟发生在从Windows 7,Windows XP执行的同一个Java客户端简单程序中。 从3台不同的机器测试。 其他地方都很棒。

      因此,我尝试使用C和PHP构建SSL简单客户端,在Windows中运行良好。 这意味着只有Java客户端方法不起作用。

      以前有没有人有任何想法或类似经历? 我看到一些帖子怀疑在WINS / DNS上,但似乎并非如此。 同样有趣的是,每台Windows机器的延迟时间总是大约4-5秒。

      非常感谢你提前发表意见。

2 个答案:

答案 0 :(得分:1)

我遇到了类似的问题。使用tcpdump,我发现从客户端到服务器的TCP连接(SYN,SYN-ACK,ACK)几乎是瞬间发生,然后是一个神秘的暂停,然后客户端实际发送数据。

tcpdump输出表明,在连接后,客户端(在Windows上运行)立即发送NetBIOS名称请求(可能是为了找出服务器的名称,也许是因为它可以选择适当的证书或其他东西)和服务器立即回复ICMP响应说NetBIOS UDP(137)端口无法访问。看起来Windows客户端忽略了该响应。 1.5秒后,Windows客户端发送另一个NetBIOS名称请求,服务器发送相同的ICMP响应。再过1.5秒后,Windows客户端发送第三个也是最后一个NetBIOS名称请求,服务器发回相同的ICMP响应。套接字数据最终在1.5秒后传输。

所以看起来Windows尝试三次来确定服务器的NetBIOS名称,每次等待1.5秒。最终(4.5秒后)它放弃并发送数据。我认为这解释了你报告的4-5秒暂停。

消除暂停的一种解决方法是添加一个主机'服务器的文件条目。 (在该文件中使用的主机名并不重要。仅仅存在IP地址就不需要NetBIOS名称解析。)也可能有其他替代方法(例如,将服务器名称添加到WINS或DNS或其他什么,取决于您的Windows机器用于名称解析的内容)。

答案 1 :(得分:0)

你抱怨写作而你只是在显示阅读代码。编写代码是什么样的?如果您没有在堆栈中使用缓冲流或写入器SSLSocket,则可能会导致数据大小爆炸达44次,这会严重影响性能。几年前我在互联网上进行了一些广泛的测试,得出的结论是,使用正确编写的代码,SSL并不比明文慢3倍。