singleton client connector - java

Picture that you have a chat program where you want to send and recive data to & from the server. would it be smart to turn the clients connection into a singleton? or will this ruin the data stream.
my example of a client singleton:
public class Client {
private static Client client;
private final int portNumber = 7070;
private Socket socket;
private Client(){
connect();
}
public static synchronized Client getClient(){
if (client == null) {
client = new Client();
}
return client;
}
public void connect(){
try {
InetAddress adr = InetAddress.getByName("localhost");
socket = new Socket(adr, portNumber);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

There are two issues with your code:
singletons are very inflexible. If you want to implement load-balancing or connection pooling in the future, your hands are tied. Only one connection is allowed. And what about reconnecting? How do you get rid of old connection and create a new one?
connecting (or any operation that has side-effects) inside a constructor is not a good practice. Imagine unit-testing this class
So I don't advice singleton connection object. Instead have a ClientConnections manager class with Client connect() method. This manager class keeps track of all opened connections, can cache them, close unused, test periodically, etc. ClientConnections is a better candidate for singleton.

Make sense to use singleton clients if you dont want more than one connection per client. This should be fine for most cases, except when you want to support sending multiple files simultaneously.

Related

Detect first client thread to register in server

A simple version of my server code can be depicted as...
public class Server implements Runnable {
static boolean isFirstClient=false;
...
...
public void run(){
ServerSocket ss=new ServerSocket(port);
while(true){
Socket s= ss.accept();
if(!isFirstClient){
isFirstClient=true;
new ClientHandler(s,true);
}
else{
new ClientHandler(s,false);
}
}
}
...
...
}
Where client handler handles the client and second parameter in the ClientHandler determines whether its the first client or not and sends the packet accordingly to the client. (I wrote a different functionality for first client to register in the server and response from server determines the first Client.)
public class Client implements Runnable(){
boolean iamFirst=false;
public void run(){
InetAddress ip = InetAddress.getByName("localhost");
Socket soc = new Socket(ip, port);
...
// response from server is stored in responsePacket.
...
iamFirst=responsePacket.isFirst();
if(iamFirst){
...
...
}
else{
...
...
}
}
}
But because of large number of clients running at the same time and also use of static variable to detect first client in server it results in running more than 1 client threads as 'firstClient'.
Can anyone suggest the best way to distinguish the first client to register in server keeping in fact that huge number of clients start at the same time?
(Note: I don't want to use sleep() function in the code to seperate one client from other client to simulate a practical scenario.)
You can make isFirstClient volatile; this makes sure all threads see the latest value of the variable.
Another approach would be to synchronise the method where you accept the clients; but since you do that in a loop it would make no sense in this case.

How do I call a method in a specific socket thread using "implements Runnable"?

I have a working Java Server (Although a tad rough around the edges) which contains 3 main classes.
The first class runs the server and gets the socket to listen on a port and passes new connections to a client handler.
The second class is a threaded client handler
The third is a protocol class which is called from the client handler and processes information. Once the information is processed, the protocol class returns a processed or formatted response back to the client handler to pass to the client.
The advantage is that the second class just needs to be loaded with what is acceptable data to accept from the socket. The data can be passed to the protocol handler, and the protocol handler can be loaded with whatever protocol you want the server to use to talk to the client.
In this instance I have loaded in a telnet-based chat class.
If, for example, someone leave the chat the client handler class may execute code such as:
for (i = 0; i < currentClientsConnected; i++) {
if(threads[i] != null && threads[i] != this) {
outputLine = threads[i].serverprotocol.processInput("** " + username + " has left the room **");
threads[i].out.printf(outputLine);
}
}
This passes "** [username] has left the room **" to the serverprotocol class, which then returns the data in the best best way to transmit the message to the clients. In this case the serverprotocol class formats the message with telnet control code which tells the client to re-draw the screen, add the new message and scroll up the existing current messages in the buffer.
I may also only want the client handler class to send message to sockets where the users are in certain chat rooms for example, so I will not want to always send to all the sockets.
In my code, this is Class 1 - the server class which accepts sockets with:
while (true) {
int i;
// Try and accept the connection
try {
clientSocket = serverSocket.accept();
// System.out.printf("Remote IP:");
// System.out.printf(clientSocket.getRemoteSocketAddress().toString());
// Find an unused socket if one is available
for (i = 0; i < maxClientsAllowed; i++) {
// If found create thread
if (threads[i] == null) {
(threads[i] = new clientThread(clientSocket, threads)).start();
break;
}
}
// If all sockets are taken
if (i == maxClientsAllowed) {
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
out.printf("Server too busy. Try later.\n");
out.close();
clientSocket.close();
}
} catch(IOException e) {
System.out.println(e);}
}
and Class 2 is a class which extends thread:
class clientThread extends Thread {
private String clientName = null;
private DataInputStream in;
private PrintWriter out;
private Socket clientSocket = null;
private final clientThread[] threads;
private int currentClientsConnected;
private serverprotocol serverprotocol;
public clientThread(Socket clientSocket, clientThread[] threads) {
this.clientSocket = clientSocket;
this.threads = threads;
currentClientsConnected = threads.length;
}
public void run() {
//stuff
}
}
I have been trying desperately to see if I can get this working using implements Runnable instead, but I have had no luck in calling a thread's processInput (or maybe that should read dataToBeProcessed) method based on the instance number of the thread (Simply called i in the code here).
The closest I have seen in:
https://github.com/ico77/chat-server-client/blob/master/src/main/java/hr/ivica/chat/server/ChatServer.java
which can take advantage as running the server as a threaded pool server.
However the sendToAll function in this case writes directly to the PrintWriters associated to the socket via a HashMap. The server does not let you send to individual protocol handler classes, or even to the individual ChatServerWorker class instances. This means I can't, for example, send a message to socket 1 and 3 only and then a separate message to socket 2.
I can't find a single example online where an instance of a socket handler can be called without using extends Thread.
Specifically,I want to keep the ability to use lines like:
threads[i].out.printf(outputLine);
or
if(threads[i].[class].[var] == 'something') {
// stuff
}
Where an integer can be used to reference the thread instance, or any class vars or methods used by that thread.
Am I missing something?
Your big problem is that you are using the Threads themselves directly as the communication layer between the Server and the Client threads, something you should not do.
Instead, create your own interface Message objects that communicate the different information between the threads, and use LinkedBlockingQueue to process them.
You should probably have:
One queue for the server to receive messages
Depending on your implementation, one queue for each of the client threads to receive messages from the server, or one queue that's shared (if it's designed so that any thread can handle any message).
So you might do something like:
Message:
public interface Message {
accept(Server server);
}
Disconnection Message (I'm just going to do one):
public class DisconnectionMessage implements Message {
String username;
public void accept(Server server) {
server.handleMessage(this);
}
}
Server Runnable:
public void run() {
while(isServerOnline()) {
Message clientMessage = queue.poll();
clientMessage.accept(this);
}
}
public void handleMessage(DisconnectionMessage msg) {
// code
}
public void handleMessage(ConnectionMessage msg) {
// code
}
etc.
Client Runnable:
private final Socket socket;
private final BlockingQueue<Message> queue;
public Client(BlockingQueue<Message> queue, Socket socket) {
this.queue = queue;
this.socket = socket;
}
public void run() {
while(true) {
Message msg = receiveMessage();
queue.offer(msg);
}
}
I am not sure if I understood your question.
The short answer: if you want to make clientThread a Runnable, just do it and then change the line
(threads[i] = new clientThread(clientSocket, threads)).start();
into
(threads[i] = new Thread(new clientThread(clientSocket, threads))).start();
If you look at the documentation:
http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#Thread(java.lang.Runnable)
Threads accept objects with Runnable supertype.
The long answer: you should not store threads directly but make an abstraction that represents a Client on the server side. This abstraction should encapsulate functionality for communication. That way, if you want to implement a different communication library you can easily subclass it and avoid breaking the open-close principle.
https://en.wikipedia.org/wiki/Open/closed_principle
Good luck.

Multi Thread Java Server

am currently working on a project where I have to build a multi thread server. I only started to work with threads so please understand me.
So far I have a class that implements the Runnable object, bellow you can see the code I have for the run method provided by the Runnable object.
public void run() {
while(true) {
try {
clientSocket = serversocket.accept();
for (int i = 0; i < 100; i++) {
DataOutputStream respond = new DataOutputStream(clientSocket.getOutputStream());
respond.writeUTF("Hello World! " + i);
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
//
}
}
} catch(IOException e) {
System.out.println(e.getMessage());
}
}
}
Bellow is the main method that creates a new object of the server class and creates a threat. initializing the Thread.
public static void main(String args[]) {
new Thread(new Server(1234, "", false)).start();
}
I know this creates a new thread but it does not serve multiple clients at once. The first client need to close the connection for the second to be served. How can I make a multi threated server that will serve different client sockets at once? Do I create the thread on the clientSocket = serverSocket.accept();
yes.
from the docs:
Supporting Multiple Clients
To keep the KnockKnockServer example simple, we designed it to listen for and handle a single connection request. However, multiple client requests can come into the same port and, consequently, into the same ServerSocket. Client connection requests are queued at the port, so the server must accept the connections sequentially. However, the server can service them simultaneously through the use of threads—one thread per each client connection.
The basic flow of logic in such a server is this:
while (true) {
accept a connection;
create a thread to deal with the client;
}
The thread reads from and writes to the client connection as necessary.
https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html

How to deal with multiple connections from the same IP?

So, I have the following code that catches a new connection, then hands that connection to its own thread to handle the client.
private void loop(int port) {
// Opens a port for connections.
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(port);
System.out.println("Server running in port " + port);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// Listens for a connection
while (onlineState == true && serverSocket != null) {
Socket clientSocket = new Socket();
try {
clientSocket = serverSocket.accept();
System.out.println(clientSocket.getInetAddress() + " has connected to the port " + clientSocket.getPort());
new Thread(new SocketThread(clientSocket)).run();
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
So, my problem here is that when I try to connect with multiple client apps to the server, the server only seems to either accept one connection at any given time. The client itself is a very simple application of the basic tutorial: it simply repeats any string that the server sends to it.
I have two guesses as to why this is happening: a) there's something wrong with my handling code, b) it's because both connections are from the same IP.
However, neither case is a good thing. Any ideas what I'm doing wrong? (Except everything)
Two things:
You want to call start(), not run() on your Thread object. The difference is that start() actually goes and does threaded stuff, like running it in the background. Calling run() from where you call it there will handle all the client communication right there, inline. That's why you only ever accept one connection - you won't accept any more until you've serviced that client.
You don't want to call clientSocket.close() in your main thread. In your implementation of SocketThread, call clientSocket.close() at the end of your run() method, probably inside a finally block.
Also, does SocketThread extend Thread? If so, you don't need new Thread(), just do
new SocketThread(clientSocket).start();
If it doesn't extend Thread, why not name it SocketRunnable or ClientRunnable or something like that.

Multithreaded Java server: allowing one thread to access another one

Hopefully the code itself explains the issue here:
class Server {
public void main() {
// ...
ServerSocket serverSocket = new ServerSocket(PORT);
while (true) {
Socket socket = serverSocket.accept();
Thread thread = new Thread(new Session(socket));
thread.start();
}
// ..
}
public static synchronized Session findByUser(String user) {
for (int i = 0; i < sessions.size(); i++) {
Session session = sessions.get(i);
if (session.getUserID().equals(user)) {
return session;
}
}
return null;
}
}
class Session {
public Session(Socket socket) {
attach(socket);
}
public void attach(Socket socket) {
// get socket's input and output streams
// start another thread to handle messaging (if not already started)
}
public void run() {
// ...
// user logs in and if he's got another session opened, attach to it
Session session = Server.findByUser(userId);
if (session != null) {
// close input and output streams
// ...
session.attach(socket);
return;
}
// ..
}
}
My question here is: Is it safe to publish session reference in Server.findByUser method, doesn't it violate OOP style, etc?
Or should I reference sessions through some immutable id and encapsulate the whole thing? Anything else you would change here?
String sessionId = Server.findByUser(userId);
if (sessionId != null && sessionId.length() > 0) {
// close input and output streams
// ...
Server.attach(sessionId, socket);
return;
}
Thomas:
Thanks for your answer.
I agree, in a real world, it would be a good idea to use dependency injection when creating a new instance of Session, but then probably also with an interface, right (code below)? Even though I probably should have unit tests for that, let's consider I don't. Then I need exactly one instance of Server. Would it then be a huge OO crime to use static methods instead of a singletone?
interface Server {
Session findByUser(String user);
}
class ServerImpl implements Server {
public Session findByUser(String user) { }
}
class Session {
public Session(Server server, Socket socket) { }
}
Good point on the attach(...) method - I've never even considered subclassing Session class, that's probably why I haven't thought how risy it might be to call public method in the constructor. But then I actually need some public method to attach session to a different socket, so maybe a pair of methods?
class Session {
public Session(Socket socket) {
attach_socket(socket);
}
public void attach(Socket socket) {
attach_socket(socket);
}
private void attach_socket(Socket socket) {
// ...
}
}
It's true that allowing clients of Session to call attach(...) doesn't seem right. That's probably one of those serious mehods only the Server should have access to. How do I do it without C++'s friendship relationship though? Somehow inner classes came to my mind, but I haven't given it much thought, so it maybe a completely wrong path.
Everytime I receive a new connection I spawn a new thread (and create a new Session instance associated with it) to handle transmission. That way while the user sends in a login command, Server is ready to accept new connections. Once the user's identity is verified, I check if by any chance he's not already logged in (has another ongoing session). If he is then I detach the onging session from it's socket, close that socket, attach the ongoing session to current socket and close current session. Hope this is more clear explanation of what actually happens? Maybe the use of a word session is a bit misfortunate here. What I really have is 4 different objects created for each connection (and 3 threads): socket handler, message sender, message receiver and a session (if it's a good solution that's a different question...). I just tried simplyfing the source code to focus on the question.
I totally agree it makes no sense to iterate over session list when you can use a map. But I'm afraid that's probably one of the smaller issues (believe me) the code I'm working on suffers from. I should've mentioned it's actually some legacy system that, no surprise, quite recently has been discoved to have some concurrency and performance issues. My task is to fix it... Not an easy task when you pretty much got only theoretical knowledge on multithreading or when you merely used it to display a progress bar.
If after this, rather lengthy, clarification you have some more insight on the architecture, I'd be more than willing to listen.
You should start by making the Server class OO (i.e. not static) and use dependency injection in the Session class:
class Server {
public Session findByUser(String user) { }
}
class Session{
public Session(Server server, Socket socket){}
}
public void attach(..) has to be private to ensure encapsulation and proper initialization. A subclass could break the Session class otherwise like this:
class BadSession extends Session{
#Override public void attach(Socket socket) {
//this is not initialized at this point
//now the instance is broken
}
}
Calling attach from a client seems to be invalid, too.
The responsibility to attach the Socket to the Session should be part of the Server. This is the right place to decide which Session gets which Socket. As far as I do understand your code you are creating a Session with a Socket. Somehow you find out that the user already has a Session (with another Socket). Now you attach the current Session to this Socket. There is now the old Socket with two Sessions and the new Socket without a Session. I think the a traditional Session should have multiple Sockets not the other wayaround:
Session session = findSession(userId);
session.attach(socket);
class Session{
List<Socket> sockets;
}
After this change the threads would not be assigned to Sessions but socket handlers, that process the input stream for one socket and change the Session accordingly.
Using synchronized for the method public static synchronized Session findByUser(String user) is not sufficient to ensure thread-safeness. You have to make sure that the look up of a session (by user) and the registration a session (if the user is not known) have to be atomic. The semantic should be analogous to putIfAbsent of ConcurrentMap. (Iterating over the session List is not efficient anyway. You should use a Map<Id, Session>.)
I hope this helps.

Categories

Resources