2011-05-26 21 views
0

我已经阅读了很多关于java套接字编程的问题/回复,但没有一个适用于我当前的问题。基本的java套接字编程问题

我写了一个基本的java ssl套接字程序,其唯一目的(目前)是在客户端和服务器之间建立一个ssl连接并由客户端发送一个签名的消息。如果消息得到服务器的验证,它应该用(true!)或者用(false!)回答。

当客户端向服务器发送“消息”并等待服务器响应时,我握手后会卡住。与此同时,服务器不处理客户端发送的消息,因此它无法响应,并且我正在等待其中的任何一个人执行该操作。

你能告诉我我犯了什么错误吗?

为了不显示大量不相关的代码,我没有包含值对象SignedMessage和Utils类。从utils类使用的方法是用于序列化和反序列化以及将字符串转换为字节数组。我知道我可以使用String.getBytes(),但我喜欢手动完成转换。所有提到的方法都经过了测试并且工作正常。

的ServerThread运行方法的代码

public void run() { 
    try { 
     InputStream in = sslSocket.getInputStream(); 
     OutputStream out = sslSocket.getOutputStream(); 

     //if I write some output here the program works well, but this is not what I want to do 
     //out.write('!'); 

     //BASE64 DECODING 
     ByteArrayOutputStream bos = new ByteArrayOutputStream(); 

     int ch; 
     while((ch = in.read()) != -1) 
      bos.write(ch); 

     ByteArrayOutputStream decoded = new ByteArrayOutputStream(); 
     Base64Encoder encoder = new Base64Encoder(); 
     encoder.decode(bos.toByteArray(), 0, bos.toByteArray().length, decoded); 

     //reconstructing the the SignedMessage object 

     SignedMessage signedMessage = (SignedMessage) Utils.deserializeObject(decoded.toByteArray()); 

     if(checkSignature(signedMessage.getMessage().getBytes("UTF-8"), signedMessage.getSignature(), signedMessage.getCertificate())){ 
      System.out.println(String.valueOf(signedMessage.getMessage())); 

      //this i where I would like to write out the answer, but the code never get executed 
      out.write(Utils.toByteArray("TRUE!")); 
      out.flush(); 
     } 
     else { 
      out.write(Utils.toByteArray("false!")); 
     } 

    } catch (IOException e) { 
     e.printStackTrace(); 
    } finally { 
     try { 
      sslSocket.close(); 
     } catch (IOException ex) { 
      ex.printStackTrace(); 
     } 
    } 

    System.out.println("Thread closed"); 
} 

这是确实的通信

static void doProtocol(SSLSocket sslSocket) throws IOException, UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException { 

    OutputStream  out = sslSocket.getOutputStream(); 
    InputStream  in = sslSocket.getInputStream(); 

    byte[] signature = generateSignature(Utils.toByteArray(Message), (PrivateKey) clientStore.getKey(Utils.CLIENT_NAME, Utils.CLIENT_PASSWORD), 
      clientStore.getCertificate(Utils.CLIENT_NAME).getPublicKey().getAlgorithm()); 

    //BASE64 ENCODING 
    byte[] object = Utils.serializeObject(new SignedMessage(Message, signature, clientStore.getCertificate(Utils.CLIENT_NAME))); 

    ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
    Base64Encoder encoder = new Base64Encoder(); 
    encoder.encode(object, 0, object.length, bos); 

    out.write(bos.toByteArray()); 
    out.flush(); 

    int ch; 
    while((ch = in.read()) != '!') 
     bos.write(ch); 

    System.out.println("Sesion closed"); 
} 
+0

看起来像你的服务器线程运行,试图从套接字读取,然后结束?从而只处理握手? – 2011-05-26 12:58:22

+0

关键是我希望服务器线程检查客户端发送的消息是否有效,并根据该信息做出答案。 当我调试代码时,服务器永远不会达到它分析客户端消息的程度,因为客户端在试图读取服务器回复时卡住了。 – proton 2011-05-26 13:02:52

+0

直到对方关闭连接,您才会读取EOS。但是我不明白为什么所有的ByteArrayOutputStreams,编码器/解码器等等。你可以用ObjectInput/OutputStreams直接封装套接字流来完成所有这些工作,并节省大量的时间和空间。 – EJP 2011-05-26 13:10:22

回答

3

while((ch = in.read()) != -1) 
     bos.write(ch); 

块永远客户端的代码。当流(连接)关闭时,这实际上会解锁。 因此,您需要确定消息的结尾。 我的意思是消息的结束并不意味着流的结束。所以当你收到你的消息后,你将无限地等待来自频道的其他消息。 正如你实际上在这里做的

while((ch = in.read()) != '!') 
    bos.write(ch); 
+0

非常感谢您的评论。我一定在仓促中错过了它。 – proton 2011-05-26 13:40:04