2011-05-26 60 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