Я пытаюсь реализовать простой адаптер ресурсов, который прослушивает сокет-соединение.Мне удалось заставить его работать с обычным сокетом, но почему-то я застрял, пытаясь заставить его работать для сокета SSL.Сокет на самом деле работает, и, кажется, соединение установлено, я мог бы получить поток ввода и выходного потока на клиенте, но каким-то образом, когда я пишу в выходной поток на клиенте, сервер никогда не получит его.
Вотсоответствующий код (да, я знаю, что это не лучшая реализация, но я просто хочу, чтобы было сделано общее дело, прежде чем пытаться найти более сложное решение):
public class SocketResAdapter implements ResourceAdapter {
private SocketListener listener = null;
private final Logger logger = Logger.getLogger(SocketResAdapter.class.getName());
@Override
public void start(BootstrapContext context) throws ResourceAdapterInternalException {
logger.info("Starting resource adapter for socket");
listener = new SocketListener(context.getWorkManager());
}
@Override
public void stop() {
listener.release();
}
}
Это класс, который слушает сокетзапросите соединение и примите его.
public class SocketListener implements Work {
private final WorkManager workManager;
private SSLServerSocket serverSocket;
private int port = 9999;
private String IP = "localhost";
private final Logger logger = Logger.getLogger(SocketListener.class.getName());
private AtomicBoolean isRunning = new AtomicBoolean(false);
final boolean isRunning() {
return isRunning.get();
}
final void setRunning(Boolean running) {
isRunning.set(running);
}
public SocketListener(WorkManager manager){
this.workManager = manager;
try {
manager.startWork(this);
} catch (WorkException e) {
e.printStackTrace();
}
}
@Override
public void run() {
setRunning(true);
try {
// for ssl
System.setProperty("javax.net.ssl.keyStore", "path/to/my/keystore/keystore.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "someweirdpassword");
InetAddress inetAddress = InetAddress.getByName(IP);
SSLServerSocketFactory l_serverSocketFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
serverSocket = (SSLServerSocket) l_serverSocketFactory.createServerSocket(port, 50, inetAddress);
while (isRunning())
{
logger.info("Accepting request from client");
SSLSocket socket = (SSLSocket) serverSocket.accept();
socket.setEnabledProtocols(new String[] {"TLSv1", "TLSv1.1", "TLSv1.2" });
workManager.scheduleWork(new SocketProcessor(socket));
}
}catch (Exception e){
setRunning(false);
}
}
@Override
public void release() {
setRunning(false);
try {
if (serverSocket!=null){
serverSocket.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
Затем клиент обслуживается другим потоком:
public class SocketProcessor implements Work {
private Socket socket;
private AtomicBoolean isRunning = new AtomicBoolean(false);
private final Logger logger = Logger.getLogger(SocketProcessor.class.getName());
final boolean isRunning() {
return isRunning.get();
}
final void setRunning(Boolean running) {
isRunning.set(running);
}
public SocketProcessor(Socket socket) throws IOException {
this.socket = socket;
}
@Override
public void run() {
setRunning(true);
logger.info("Running socket processor");
try{
LineNumberReader in = new LineNumberReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
final PrintStream socketOutput = new PrintStream(socket.getOutputStream());
String line;
int size = 0;
while ((line = in.readLine()) != null) {
logger.info("Reading line");
if ( "EXIT".equals( line )){
socket.close();
break;
}else{
socketOutput.println(line);
size += line.length();
socketOutput.flush();
}
}
}catch (Exception e){
e.printStackTrace();
setRunning(false);
}
finally {
closeSocket();
}
}
@Override
public void release() {
setRunning(false);
closeSocket();
}
private void closeSocket(){
try {
if(!socket.isClosed()) {
socket.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
Вот соответствующий код клиента
public class Main {
public static void main(String[] args){
int port = 9999;
String address = "localhost";
SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory.getDefault();
try{
InetAddress inetAddress = InetAddress.getByName("localhost");
SSLSocket socket = (SSLSocket) factory.createSocket(inetAddress, port);
printSocketInfo(socket);
//socket.con
//socket.startHandshake();
if(socket.isConnected())
System.out.println("THE SOCKET IS CONNECTED");
final OutputStream outputStream = socket.getOutputStream();
String sendString = args.length == 0 ? "THES IS DE DEFAULT STRING TO SEND" : args[0];
outputStream.write(sendString.getBytes());
System.out.println("Flushing the output stream : " + sendString);
outputStream.flush();
final InputStream inputStream = socket.getInputStream();
final BufferedReader rd = new BufferedReader(new InputStreamReader(inputStream));
String str;
while ((str = rd.readLine()) != null) {
System.out.println("LOOPS");
System.out.println(str);
}
rd.close();
socket.close();
}catch(Exception e){
e.printStackTrace();
}
}
private static void printSocketInfo(SSLSocket s) {
System.out.println("Socket class: "+s.getClass());
System.out.println(" Remote address = "
+s.getInetAddress().toString());
System.out.println(" Remote port = "+s.getPort());
System.out.println(" Local socket address = "
+s.getLocalSocketAddress().toString());
System.out.println(" Local address = "
+s.getLocalAddress().toString());
System.out.println(" Local port = "+s.getLocalPort());
System.out.println(" Need client authentication = "
+s.getNeedClientAuth());
SSLSession ss = s.getSession();
System.out.println(" Cipher suite = "+ss.getCipherSuite());
System.out.println(" Protocol = "+ss.getProtocol());
}
}
Я успешно получаюинформация о сеансе и сокете печати уже показывает принятый набор и протокол.Там нет ошибки ни на сайте клиента, ни на сайте сервера, сервер просто не получает данные, отправленные с клиента.Интересно, что я сделал не так?Кстати, я использую адаптер на Weblogic.