我有一個(gè)多線程聊天服務(wù)器,我已將其轉(zhuǎn)換為使用 Java SSL 套接字。與我在 Github 上轉(zhuǎn)換的版本相比,您可以看到?jīng)]有 SSL 套接字的版本。(主分支有 SSL,其他分支有常規(guī)套接字)這個(gè)原始模型(沒(méi)有 SSL)使用由客戶端控制的“ServerThreads”通過(guò)向服務(wù)器端的“ClientThreads”發(fā)送消息來(lái)與其他客戶端通信,然后將它們的消息回顯到所有其他 ServerThreads。這里是ServerThread_w_SSL的run方法(客戶端) @Overridepublic void run(){ System.out.println("Welcome :" + userName); System.out.println("Local Port :" + socket.getLocalPort()); System.out.println("Server = " + socket.getRemoteSocketAddress() + ":" + socket.getPort()); //setup handshake socket.setEnabledCipherSuites(socket.getSupportedCipherSuites()); try{ PrintWriter serverOut = new PrintWriter(socket.getOutputStream(), false); InputStream serverInStream = socket.getInputStream(); Scanner serverIn = new Scanner(serverInStream); // BufferedReader userBr = new BufferedReader(new InputStreamReader(userInStream)); // Scanner userIn = new Scanner(userInStream); socket.startHandshake(); while(!socket.isClosed()){ if(serverInStream.available() > 0){ if(serverIn.hasNextLine()){ System.out.println(serverIn.nextLine()); } }原始程序使用常規(guī)套接字,但在轉(zhuǎn)換為 SSL 套接字后,我遇到了一個(gè)問(wèn)題:輸入沒(méi)有從 ClientThreads(服務(wù)器端)回顯到 ServerThreads(客戶端)。在我第一次嘗試轉(zhuǎn)換為 SSL 時(shí),我使用了證書、密鑰庫(kù)和信任庫(kù)。我遇到了同樣的問(wèn)題,就像我在這里沒(méi)有它們一樣,而是只使用依賴于 JDK 附帶的 cacerts 文件的默認(rèn)套接字工廠。請(qǐng)注意,在遇到此錯(cuò)誤之前,要解決的第一個(gè)問(wèn)題是客戶端和服務(wù)器之間發(fā)生的握手失敗。由于 SSL 和 Java PrintWriter 類的工作方式,握手在第一次調(diào)用 PrintWriter.flush() 時(shí)啟動(dòng),一旦客戶端向服務(wù)器發(fā)送聊天消息,就會(huì)發(fā)生這種情況。這只能通過(guò)在 ClientThread(服務(wù)器)和 ServerThread(客戶端)中手動(dòng)啟用支持的密碼套件來(lái)解決,然后至少在 ClientThread 中調(diào)用 SSLSocket.StartHandshake(),如果不是同時(shí)調(diào)用的話?,F(xiàn)在服務(wù)器正在接收來(lái)自客戶端的消息,但它沒(méi)有將它們回顯給客戶端。當(dāng)我在調(diào)試器中運(yùn)行它并嘗試單步執(zhí)行代碼時(shí),我發(fā)現(xiàn) ClientThread 接收客戶端的消息并通過(guò)為每個(gè) ClientThread 調(diào)用 PrintWriter 上的 write() 將其發(fā)送回,然后刷新 ()。ServerThread 應(yīng)該通過(guò)調(diào)用 InputStream.available() 在不阻塞的情況下檢查輸入來(lái)接收它,但 available() 總是返回“0 字節(jié)”,因此它永遠(yuǎn)不會(huì)命中 Scanner.nextLine()因此 Printwriter.write() 和 .flush() 不發(fā)送數(shù)據(jù)或 InputStream.available() 不讀取數(shù)據(jù)。
多線程服務(wù)器轉(zhuǎn)換為SSL后,回顯消息的問(wèn)題
狐的傳說(shuō)
2021-08-19 21:23:47