Search code examples
javasocketsserverclientserversocket

Multi-threaded Server Client Address already in use


What I'm trying to do is make receiver class in the server which receives the sent messages from the client and make a sender class in the client. I'm trying to make the receiver in the server first 'cause I'll probably figure out how to do that in the client side after learning it. But doing this gives me java.net.BindException: Address already in use: JVM_Bind. I think it's because I have another Server server = new Server(); in the receiver. How do I solve this?

Server.java

package MultithreadingServerClient;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class Server {
    ServerSocket serverSocket = new ServerSocket(3000);
    Socket socket = serverSocket.accept();
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    PrintWriter printWriter = new PrintWriter(socket.getOutputStream(), true);

    public Server() throws IOException {
    }

    public static void main(String[] args) {
        Thread serverSender = new Thread(new ServerSender());
        Thread serverReceiver = new Thread(new ServerReceiver());
        serverSender.start();
        serverReceiver.start();
    }
}

// Sender class
class ServerSender implements Runnable {

    @Override
    public void run() {
        try {
            Server serve = new Server();
            Scanner scanner = new Scanner(System.in);

            String msg = "";
            while (!msg.equalsIgnoreCase("exit")) {
                System.out.print("Server: ");
                msg = scanner.nextLine();

                serve.printWriter.println(msg);
            }

        } catch (IOException e) {
            System.err.println("Sender Error " + e);
        }
    }
}

class ServerReceiver implements Runnable {
    @Override
    public void run() {
        try {
            Server server = new Server();

            System.out.println(server.bufferedReader.readLine());
        } catch (IOException e) {
            System.err.println("Receiver Error " + e);
        }
    }
}

Client.java

package MultithreadingServerClient;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

public class Client {
    Socket socket = new Socket("localhost", 3000);
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    PrintWriter printWriter = new PrintWriter(socket.getOutputStream());

    public Client() throws IOException {
    }

    // Receive messages
    public static void main(String[] args) {
        try {
            Client client = new Client();

            while (true) {
                System.out.println("Server: " + client.bufferedReader.readLine());
            }
        } catch (IOException e) {
            System.out.println("Server Closed!");
        }
    }
}

class ClientSender implements Runnable {
    @Override
    public void run() {
        try {
            Client client = new Client();

            client.printWriter.println("Test message: send to Server");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Solution

  • Don't create multiple instances of Server, you may create the instance in main then just pass the bufferedReader to the receiver class, and the printWriter to the sender class.

    Sender class :

    class ServerSender implements Runnable {
    
    
        private PrintWriter writer;
    
        public ServerSender(PrintWriter printWriter){
    
            writer = printWriter;
        }
    
        @Override
        public void run() {
            try {
    
                Scanner scanner = new Scanner(System.in);
    
                String msg = "";
                while (!msg.equalsIgnoreCase("exit")) {
                    System.out.print("Server: ");
                    msg = scanner.nextLine();
    
                    writer.println(msg);
                }
    
            } catch (IOException e) {
                System.err.println("Sender Error " + e);
            }
        }
    }
    

    Receiver class :

    class ServerReceiver implements Runnable {
    
        private BufferedReader reader;
    
        public ServerReceiver(BufferedReader bufferedReader){
    
           reader = bufferedReader;
    
        }
    
        @Override
        public void run() {
            try {
    
                System.out.println(reader.readLine());
            } catch (IOException e) {
                System.err.println("Receiver Error " + e);
            }
        }
    }
    

    Method main in Server :

    public static void main(String[] args) {
    
        Server serve = new Server();
        Thread serverSender = new Thread(new ServerSender(serve.printWriter));
        Thread serverReceiver = new Thread(new ServerReceiver(serve.bufferedReader));
        serverSender.start();
        serverReceiver.start();
    }