The problem: I have a Class that contains a Map< String, Socket >, which is static, and I use it as reference to get the Socket given the name of the client. But in order to do this, when the client is accepted by the server I should save his identifier, too. The problem is that his identifier is also the name of the client, and I don't know it until the client sends it and this happens only after the client is accepted.
My code:
Server Socket
public class SocketServer {
private int port;
private ServerSocket serverSocket;
private ExecutorService executorService;
public SocketServer(int port) {
this.port = port;
executorService = Executors.newCachedThreadPool();
}
public void startServer() {
initServer();
handleConnections();
executorService.shutdown();
}
private void initServer() {
try {
serverSocket = new ServerSocket(port);
} catch (IOException e) {
// log exception
}
}
private void handleConnections() {
while (true) {
try {
Socket socket = serverSocket.accept();
executorService.submit(new ClientHandler(socket));
} catch (IOException e) {
// log exception
break;
}
}
}
}
Client Handler
public class ClientHandler implements Runnable {
private Socket socket;
public ClientHandler(Socket socket) {
this.socket = socket;
}
public void run() {
try {
Thread thread = new Thread(new Reader(socket));
thread.start();
} catch (IOException e) {
// log exception
}
}
private void close() {
try {
objectOutputStream.close();
socket.close();
} catch (IOException e) {
// log exception
}
}
}
Reader
public class Reader implements Runnable {
private final static Logger LOGGER = Logger.getLogger(Reader.class.getName());
private Socket socket;
private ObjectInputStream objectInputStream;
public Reader(Socket socket) throws IOException {
this.socket = socket;
objectInputStream = new ObjectInputStream(socket.getInputStream());
}
@Override
public void run() {
while (true) {
try {
Visitable visitable = (Visitable)objectInputStream.readObject();
Visitor visitor = new VisitorImpl();
visitable.acceptVisitor(visitor);
} catch (IOException | ClassNotFoundException e) {
// log exception
}
}
}
}
In the while(true) i keep reading and I handle every kind of request through a Visitor Pattern. Here I have a Class implementing Visitable that can contain the Socket, so if I can set it the Visitor can register the client with his String and Socket, but in this part of the program I don't have access to the setters of the classes implementing the Visitable. I could do something like
if (visitable instanceof VisitableImplWithSocket) {
((VisitableImplWithSocket) visitable).setSocket(socket);
}
But I need this only one time (for every client) right after the client is accepted and it's inside a while loop, so I don't really like it. Any alternatives?
NOTE: I need the Class with the Map< String, Socket > because a client can decide how to connect to the server (socket or RMI) and I need to keep a reference to both the Socket and the Class on which I can do a RMI callback. This class looks like
public class ListConnections {
private static Map<String, Socket> CLIENT_SOCKET_MAP;
private static Map<String, Registrable> CLIENT_RMI_MAP;
...
}
Aucun commentaire:
Enregistrer un commentaire