ServerSocket connection with more than one client - java

Folks. I'm newbie in network programming and come across the following issue. I need to write the server which can maintain a connection with more than one client simultaneously. What I've written is the following:
Main class:
public class Main {
public static void main(String args[]) throws Exception{
ConnectionUtils.waitForClients();
}
}
ConnectionUtils class:
public class ConnectionUtils {
private static ServerSocket server;
static{
try {
server = new ServerSocket(54321);
} catch (Exception e) {
}
}
private static Runnable acceptor = new Runnable() {
#Override
public void run() {
try {
Client c = new Client(server.accept());
new Thread(acceptor).start();
c.sendLine("Hello client \n");
} catch (Exception e) {
}
}
};
public static void waitForClients(){
Thread clientAcceptor = new Thread(acceptor);
clientAcceptor.start();
}
}
and it works, more-or-less. But what is the downside of that approach? I suspect there're too much disadvantage, but I can't catch their.

The problem is that you creating an infinite number of threads where threads are expensive resources. You should be using a ThreadPool to limit the number of threads created in your program.
Consider using Executors instead of using this low-level code, In Oracle documentation about Executors, there is an example similar to what you doing. Check it out!

Heh interesting. I wouldn't expect it to be wrong but it sure isn't how I'd write it.
I'd probably have 1 thread in an infinite (semi-infinite with stop condition) loop that accepts and spawn threads, rather than something that looks like a recursive method but isn't. However as far as I can see it's not wrong.
Having said that, if you don't use your main thread for anything, why not do something like (and keep in mind i'm not a network programmer either)
public class ConnectionUtils {
protected boolean stop = false;
public static void waitForClients() {
while (!stop) {
Client c = new Client(server.accept());
new Thread(new ClientDelegate(c)).start();
}
}
}
public static class ClientDelegate implements Runnable {
private Client client;
public ClientDelegate(Client c) { this.client = c; }
public static void run() {
c.sendLine("Hello client\n");
}
}

Related

What is the gold standard for creating a main() loop that waits for a Thread in Java

I was tasked to write a small server application. It is supposed to be started via the console and then run in the background, processing some network traffic and calculating stuff locally until it receives a shutdown signal. I am pretty sure i can handle all of that - except the very basic application architecture. I am super unsure how to bring my main loop to wait for the application to finish. So here is my current code, cleaned up and omitting unnecessary parts.
public class TestServer {
public static Logger logger;
private static Boolean abortStartup = false;
private static ServerModule server;
public static void main(String[] args) {
System.out.println("Starting Server...");
initializeServer(); //this function reads config file, and initializes all variables and stuff. If anything goes wrong, abortStartup is set to true
if (!abortStartup) {
runMainLoop();
}
if (!abortStartup) {
cleanup(); //clean up all initialized variables and objects
}
System.out.println("Goodbye.");
}
private static void runMainLoop() {
//This is the main loop. Run this until application terminates.
logger.log(null, "Starting main loop...", Logger.LOGLEVEL_NOTE);
server.run();
while (server.isAlive()) {
//wait until server dies.
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
logger.log(null, "Interrupted during wait for main thread.", Logger.LOGLEVEL_ERROR);
}
}
logger.log(null, "Done.", Logger.LOGLEVEL_NOTE);
}
ServerModule looks like this:
public class ServerModule{
public Boolean shutdown = false;
private Boolean stayAlive = true;
public ServerModule(){
//setup everything
}
public void run() {
//initalize timers, instantiate objects etc.. add listeners and everything. At some point, a network message will set stayAlive to false;
}
public Boolean isAlive() {
return stayAlive;
}
Now for the actual question: is there a more elegant or more efficient way to go about this? i am talking about this part specifically:
while (server.isAlive()) {
//wait until server dies.
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
logger.log(null, "Interrupted during wait for main thread.", Logger.LOGLEVEL_ERROR);
}
Is thread.sleep okay here? Could or should i even omit it? I want to wait here at this very point of my code, so i can clean up after execution stops.
You can make your server something runnable, pack that into a Thread and join!
Example
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
try {
Thread.sleep(5000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System.out.println("Starting Server!");
t.start();
t.join();
System.out.println("Server is done!");
}
Also you can use CountDownLatch for your purpose, see example:
public class ServerModule extends Thread {
private final CountDownLatch latch;
ServerModule(CountDownLatch latch) {
this.latch = latch;
}
#Override
public void run() {
try {
Thread.sleep(1000L);
//decrease counter of the latch when job is done
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// as ctor arg use threads count for countdown
CountDownLatch latch = new CountDownLatch(1);
System.out.println("Start server");
ServerModule serverModule = new ServerModule(latch);
serverModule.start();
try {
//waiting until latch count will be 0
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Server is done");
}
}
Also with CountDownLatch you can create multiple server instances and waiting them in main thread until they are all done.
It depends on how you're managing your threads.
At the lowest level Java thread API, your main thread can wait for the server thread to complete with:
serverThread.join();
Look at the Thread API for more options, such as putting a timeout on the join() (so you can take increasingly drastic measures to make it end).
Higher level threading abstractions such as Executor, Future, ForkJoinTask etc. give you the same ability with different APIs. A thorough exploration of these is beyond the scope of a SO answer -- Oracle has tutorials on concurrency, or there are books.

Multithreaded Java worker with a size restricted resource pool

I have this 'Worker' class, which uses a resource 'Client'.
There may be any number of threads, running the 'Worker' at any given time.
The 'Client' is not thread-safe, thus I'm using 'ThreadLocal' for it.
The 'Client' connects to some server and executes a HTTP 'Request' that the worker feeds the 'Client'.
public class Worker {
// Client is NOT thread-safe !!!
private static ThreadLocal<Client> client = new ThreadLocal<Client>();
#Override
protected void onGet(Request req) {
handleRequest(req);
}
private void handleRequest(Request req) {
someRunnableExecutor(new Runnable() {
#Override
public void run() {
get_client().send_req(req);
}
});
}
private Client get_client() {
Client c = client.get();
if (c == null) {
c = new Client();
client.set(c);
}
return c;
}
At the current implementation (above), stripped down for clarity, there are as many "active" 'Clients' as there are running 'Workers'.
This is a problem because the server is being exhausted.
What I can do is only fix the 'Worker'. Have no access to the 'Client', server or the executor that runs the workers.
What I want to do is to have a Queue of 'Client'(s) and a piece of a synchronized code, in the 'Worker', that takes a 'Client' off the Queue, if the Queue is empty the 'Worker' should wait till there is one in the Queue for him to take. Then put the 'Client' back into the Queue - synchronized as well.
I really want to keep it as simple as possible, with the possible minimum changes made to the code.
No new classes, no factories, just some data structure to hold the 'Client'(s) and synchronization.
I am a bit puzzled with how to achieve that generally, as well as by the fact that the 'Client' is not thread-safe and that I have to 'ThreadLocal'(ize) it. Is this how do I put that in a Queue?
private static Queue<ThreadLocal<CLient>> queue =
new LinkedList<ThreadLocal<CLient>>();
Also, how/where do I initialize that Queue, once, with say 5 clients?
Please share your thoughts.
You don't need ThreadLocal here, as you want to have less Clients than Workers. All you need in BlockingQueue.
Notice! I supposed that Client's send_req is synchronous, if it's not - the code needs some changes in run() method
public class Worker {
private static final int CLIENTS_NUMBER = 5;
private static final BlockingQueue<Client> queue = new LinkedBlockingQueue<>(CLIENTS_NUMBER);
static {
for (int i = 0; i < CLIENTS_NUMBER; i++)
queue.put(new Client());
}
#Override
protected void onGet(Request req) {
handleRequest(req);
}
private void handleRequest(Request req) {
someRunnableExecutor(new Runnable() {
#Override
public void run() {
try {
Client client = takeClient();
client.send_req(req);
putClient(client);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
}
private Client takeClient() throws InterruptedException {
return queue.take();
}
private void putClient(Client client) throws InterruptedException {
queue.put(client);
}
}

Exception in thread "Thread-0" java.util.NoSuchElementException?

I am new to using threads. In another class an instance of the ConnectionMaster class is created and started (extends thread). A Client object is given to the ConnectionMaster object which adds it to the list. The overridden run() method of the Thread class essentially listens for a client to be added to the list. Indeed it does listen and "hears" when a Client object is added to the list. However, although .hasNext() returns true .Next() causes an exception. What am I doing wrong?
The following methods are from class ConnectionMaster which extends Thread:
Constructor
public ConnectionMaster(){
clients = new Vector<>();
listIterator = clients.listIterator();
}
Public method for adding client objects to the list
#Override
public synchronized void addClient(Client client) {
listIterator.add(client);
}
This is the overridden thread method of the class Thread. It consistently checks for elements added to the list.
#Override
public void run(){
while(true){
while(listIterator.hasNext()){
processClient(listIterator.next()); //this is where error occurs
listIterator.remove();
}
while(listIterator.hasPrevious()){
processClient(listIterator.previous());
listIterator.remove();
}
}
}
////////////////////////////////UPDATE////////////////////////////////////
Thank You OldCurmudgeon and Stephen C.
Based on your feedback, my code has been modified thus:
Constructor
public ConnectionMaster(){
clients = new ArrayBlockingQueue<Client>(1024);
}
Method for receiving client objects
#Override
public synchronized void addClient(Client client) {
try {
clients.put(client);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Listener
#Override
public void run(){
while(true){
try {
processClient((Client)clients.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
This is a very strange way to implement Producer/Consumer. The usual way is to use a BlockingQueue.
public class TwoThreads {
public static void main(String args[]) throws InterruptedException {
System.out.println("TwoThreads:Test");
new TwoThreads().test();
}
// The end of the list.
private static final Integer End = -1;
static class Producer implements Runnable {
final BlockingQueue<Integer> queue;
public Producer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
#Override
public void run() {
try {
for (int i = 0; i < 1000; i++) {
queue.add(i);
Thread.sleep(1);
}
// Finish the queue.
queue.add(End);
} catch (InterruptedException ex) {
// Just exit.
}
}
}
static class Consumer implements Runnable {
final BlockingQueue<Integer> queue;
public Consumer(BlockingQueue<Integer> queue) {
this.queue = queue;
}
#Override
public void run() {
boolean ended = false;
while (!ended) {
try {
Integer i = queue.take();
ended = i == End;
System.out.println(i);
} catch (InterruptedException ex) {
ended = true;
}
}
}
}
public void test() throws InterruptedException {
BlockingQueue<Integer> queue = new LinkedBlockingQueue<>();
Thread pt = new Thread(new Producer(queue));
Thread ct = new Thread(new Consumer(queue));
// Start it all going.
pt.start();
ct.start();
// Wait for it to finish.
pt.join();
ct.join();
}
}
What am I doing wrong?
Quite a lot actually.
First thing you are doing wrong is (apparently) using an ListIterator object in multiple threads. The ListIterator and Iterator implementations for Vector are not thread-safe1, so what you are doing is potentially hazardous.
The second thing is that even if the iterators / list iterators were thread-safe, you are performing a sequence of operations (e.g. hasNext, next, remove) without doing anything to ensure that the sequence of operations is performed in a way that is threadsafe. There is a distinct possibility that two threads could be performing the same sequence simultaneously on the shared iterator, and that one could interfere with the other.
I'm not sure what to suggest in order to fix your code. Two threads sharing an iterator is not going to work.
It would probably be better to ditch it, and use some kind of Queue as suggested by #OldCurmugeon.
Either problem 1 or problem 2 (as outlined above) could give rise to NoSuchElement exceptions.
1 - This is apparent from examining the source code - http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/Vector.java#Vector.ListItr .

Java - Synchronized

Hi i have made a something that extends thread that adds adds an object that has a IP in it. then i made two instances of this thread and started them. they use the same list.
I now want to use Synchronized to stop the concurrent update problem. But its not working and i cant work out why.
My main class:
import java.util.*;
import java.io.*;
import java.net.*;
class ListTest2 {
public static LinkedList<Peer> myList = new LinkedList<Peer>();
public static void main(String [] args) {
try {
AddIp test1 = new AddIp(myList);
AddIp test2 = new AddIp(myList);
test1.start();
test2.start();
} catch(Exception e) {
System.out.println("not working");
}
}
}
My thread class:
class AddIp extends Thread {
public static int startIp = 0;
List<Peer> myList;
public AddIp(List<Peer> l) {
myList = l;
}
public synchronized void run() {
try {
startIp = startIp+50;
int ip = startIp;
InetAddress address = InetAddress.getByName("127.0.0.0");
Peer peer = new Peer(address);
while(ip <startIp+50) {
ip++;
address = InetAddress.getByName("127.0.0."+ip);
peer = new Peer(address);
myList.add(peer);
if(myList.indexOf(peer)== (myList.size() -1)) {
} else {
System.out.println("Lost"+peer.peerIp);
}
}
} catch(Exception e) {
}
}
}
Can anyone help me out here im lost for ideas thanks.
public synchronized void run()
Synchronizes on calling instance: this.
So,
1st thread synchronizes on test1 and 2nd thread synchronizes on test2, which doesn't help at all.
You want to synchronize on the shared resource, in this case: myList
public void run() {
synchronize(myList){
//your Logic
}
}
As a side note: Implement runnable instead of extending a Thread. Read more here.
You'd be better off implementing Runnable oppose to extending thread
also
public void run() {
synchronize(list){
//stuffs
}
}
they use the same list.
You can try to use Vector instead List. Vector is synchronized
or set your List to be synchronized:
List myList = Collections.synchronizedList(myList);
instead to use:
synchronize(myList){
}
The easiest way is to use a List implementation that can handle multiple threads. Try CopyOnWriteArrayList.

How can I start a server in a background thread and know that the server did not throw exception on startup?

I have a class which encapsulates a Server Socket i.e. a server functionality.
The interface of the class is:
class Server{
public void start();
public void stop();
}
the start is as follows:
public void start(){
ExecutorService tp = Executors.newSingleThreadExecutor();
while(!stop){
try {
Socket clientConnection = serverSocket.accept();
tp.execute(new ClientProcessor(clientConnection));
} catch (IOException e) {
stop = true;
}
}
I have trouble figuring out how I would start this without blocing my main.
I mean I need to start the server from a background thread so I thought of the following:
ExecutorService tp2 = Executors.newSingleThreadExecutor();
tp.submit(new Runnable(){
public void run(){
Server s = new Server();
s.start();
}
});
}
But what I want is to know that the server started and did not throw an exception. How can I do that?
I.e. how can I know from my main thread that the background server started fine and so I can continue with the rest actions?
Start the server.
Wait a bit.
Try to connect to it on the local stack. If the connect succeeds, you have a winner - just close the temp connection.
Here is a very simple example (though there are many better - and more complicated - ways):
interface Server implements Thread{
public void startup();
public void shutdown();
}
class MyServer implements Server{
private Exception serverError=null;
ExecutorService singleThreadManager;
public Exception getServerError(){
return serverError;
}
public void run(){
while(!stop){
try {
Socket clientConnection = serverSocket.accept();
singleThreadManager.execute(new ClientProcessor(clientConnection));
} catch (IOException e) {
serverError = e;
// stop = true;
shutdown(); // shutdown cleanly after exception
}
}
}
public void startup(){
singleThreadManager = Executors.newSingleThreadExecutor();
// do setup tasks and then
start(); // thread.run() will now be called asynchronously
}
}
public static void main (String ... args){
MyServer s = new MyServer();
s.startup();
// whenever you want you can now call
Exception x = s.getServerError();
// to see whether the server has shutdown because of an error.
}
maybe you can implement an Event Handler into your main application. Your main application should be registered as eventlistener to your server class.
Please have a look at the following link, it shows you an example of event handling for C# and the same example for Java
http://scatteredcode.wordpress.com/2011/11/24/from-c-to-java-events/
A simple way of doing this would be to collect all exceptions in a collection and return them to the foreground thread at some point in time.
class Server{
private Collection<? extends Exception> exceptions = new ArrayList<Exception>();
public void start()
{
try{ /* do something*/ }
catch(Exception e)
{
exceptions.add(e)
}
}
public void stop();
public Collection<Exception> getAllExceptions()
{
return exceptions;
}
public boolean checkOk()
{
return 0 == exceptions.size();
}
}
Elaboration on how to transfer data between threads:
If you declared your server similarly to my suggestion above, then we can change the code you have used to spawn your server to transfer the serverStartupOk information:
ExecutorService tp2 = Executors.newSingleThreadExecutor();
final boolean[] result = new boolean[1]; //Final object so it can pass between threads
tp.submit(new Runnable(){
public void run(){
Server s = new Server();
s.start();
result[0] = s.checkOk(); // Retrieve the check from the server, store it in
// final array variable
}
});
boolean serverStartupOk = result[0];
System.out.println("Server startup succesful: " + Boolean(serverStartupOk).toString());
}
Use your own ThreadPoolExecutor instead of the pre-baked ones in Executors. Then override the afterExecute hook provided by TPE to do whatever you want with the exceptions.
I'm reading a bit between the lines here, but it looks like you want to know if the initial listen on the socket succeeded or not. If you wanted to wait and see if any client failed, then there would be no need to run it in a different thread.
If that's correct, then you can catch any exceptions emitted by the initial TCP server socket instantiation before you start the thread to handle client connections. Pass the server in to the new thread, instead of creating it in the new thread.

Categories