Рассмотрим следующий сервер:
public class TestServer {
public static void main(String[] args) {
String ksName = "/some/path/keystore-server.jks";
char ksPass[] = "password".toCharArray();
char ctPass[] = "pswd".toCharArray();
KeyStore ks;
try {
ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(ksName), ksPass);
KeyManagerFactory kmf =
KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, ctPass);
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(kmf.getKeyManagers(), null, null);
SSLServerSocketFactory ssf = sc.getServerSocketFactory();
SSLServerSocket s = (SSLServerSocket) ssf.createServerSocket(SERVER_PORT);
while(true){
SSLSocket sslsocket = (SSLSocket) s.accept();
System.out.println("New Client accepted");
TestThread t = new TestThread(sslsocket);
t.run();
}
} catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException | UnrecoverableKeyException | KeyManagementException ex) {
Logger.getLogger(TotalControlServer.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Выше показан простой сервер, который принимает несколько клиентов: сразу после принятия нового соединения отправляется новый поток (TestThread) для обработки входящих запросов клиента. Вот код для TestThread:
public class TestThread implements Runnable {
SSLSocket sslsocket;
public TestThread(SSLSocket sslsocket) {
this.sslsocket = sslsocket;
}
@Override
public void run() {
ObjectInputStream is = null;
ObjectOutputStream os = null;
try {
is = new ObjectInputStream(sslsocket.getInputStream());
os = new ObjectOutputStream(sslsocket.getOutputStream());
while(true){
String p = (String) is.readObject();
System.out.println("We got: " + p);
os.writeObject(p.concat(p));
os.flush();
}//while
} catch (IOException ex) {
Logger.getLogger(CmdLineService.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(CmdLineService.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
is.close();
os.close();
this.sslsocket.close();
} catch (IOException ex) {
Logger.getLogger(CmdLineService.class.getName()).log(Level.SEVERE, null, ex);
}
}
}//run
}
Достаточно просто, он просто бесконечно читает строки и отправляет обратно свою конкатенацию.
Клиент тоже довольно простой:
public class TestClient {
public static void main(String[] args) {
System.setProperty("javax.net.ssl.trustStore" , "/path/keystore-client.jks") ;
ObjectOutputStream os = null;
ObjectInputStream is = null;
SSLSocket sslsocket = null;
try {
SSLSocketFactory f = (SSLSocketFactory) SSLSocketFactory.getDefault();
sslsocket = (SSLSocket) f.createSocket("localhost", SERVER_PORT);
sslsocket.startHandshake();
System.out.println("Authentication done");
os = new ObjectOutputStream(sslsocket.getOutputStream());
is = new ObjectInputStream(sslsocket.getInputStream());
BufferedReader b = new BufferedReader(new InputStreamReader(System.in));
boolean exit = false;
while(!exit){
System.out.print("> ");
String line = b.readLine();
os.writeObject(line);
os.flush();
String s = (String) is.readObject();
System.out.println(s);
}//while
} //main
catch (IOException ex) {
Logger.getLogger(TotalControlCmdClient.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(TestClient.class.getName()).log(Level.SEVERE, null, ex);
} finally {
try {
is.close();
sslsocket.close();
} catch (IOException ex) {
Logger.getLogger(TestClient.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Просто зацикливается на неопределенный срок, отправляя строки и читая строку.
Это отлично работает для одного клиента. Однако, если я запускаю другой клиент, он не подключается! Кажется, я столкнулся с какой-то проблемой голодания потока.
Как я могу это исправить?