【问题标题】:Multi-threaded Server Client Address already in use多线程服务器客户端地址已在使用中
【发布时间】:2018-02-19 09:26:30
【问题描述】:

我正在尝试做的是在服务器中创建接收器类,该接收器从客户端接收发送的消息,并在客户端中创建一个发送器类。我正在尝试首先在服务器中制作接收器,因为我可能会在学习后弄清楚如何在客户端做到这一点。但是这样做给了我java.net.BindException: Address already in use: JVM_Bind。我认为这是因为我在接收器中有另一个Server server = new Server();。我该如何解决?

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();
        }
    }
}

【问题讨论】:

标签: java sockets server client serversocket


【解决方案1】:

不要创建Server 的多个实例,您可以在main 中创建实例,然后将bufferedReader 传递给接收者类,将printWriter 传递给发送者类。

发件人类:

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);
        }
    }
}

接收器类:

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);
        }
    }
}

Server 中的方法 main

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();
}

【讨论】:

    【解决方案2】:

    您有两个线程在同一个端口 (3000) 上启动一个新的连接实例。我假设您正试图让一个线程从服务器接收消息,另一个线程用于向客户端发送消息。我不认为你需要有这样的设计。这可以在单线程环境中完成。不需要客户端(发送方和接收方)和服务器(发送方和接收方)。

    ServerSocket.accept();方法会监听所有传入指定端口号的消息。

    为了让服务器向客户端发送回复。您可以使用 DataOutputStream.writeUTF() & DataOutputStream.flush() 方法。

    客户端也是如此。看看下面的程序。

    class Server {
        public static void main(String args[]) throws IOException {
            try (ServerSocket serverSocket = new ServerSocket(3333); // open connection at port 3333
                    Socket socket = serverSocket.accept();
                    DataInputStream inputStream = new DataInputStream(socket.getInputStream());) {
                DataOutputStream outStream = new DataOutputStream(socket.getOutputStream());
                BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
                String messageFromClient = "", messageToBeClient = "";
                while (!messageFromClient.equals("exit")) {
                    messageFromClient = inputStream.readUTF();
                    System.out.println("Message From Client :  " + messageFromClient);
                    messageToBeClient = reader.readLine();
                    outStream.writeUTF(messageToBeClient);
                    outStream.flush();
                }
            }
        }
    }
    
    
    class Client {
        public static void main(String args[]) throws Exception {
            try (Socket socket = new Socket("localhost", 3333); // establish connection to the open socket at port 3333
                    DataInputStream inputStream = new DataInputStream(socket.getInputStream());) {
                DataOutputStream outStream = new DataOutputStream(socket.getOutputStream());
                BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
                String messageFromServer = "", messageToServer = "";
                while (!messageToServer.equals("exit")) {
                    messageToServer = reader.readLine();
                    outStream.writeUTF(messageToServer);
                    outStream.flush();
                    messageFromServer = inputStream.readUTF();
                    System.out.println("Message From Server :  " + messageFromServer);
                }
            }
        }
    }
    

    【讨论】:

    • 感谢您的回答。我们在学校学习套接字编程,我们的任务是制作一个程序,使用与 oracle 提供的 KnockKnockServer 程序类似的方法相互通信。由于我已经完成了它,这让我对使用多线程进行处理感到好奇,这样我就可以同时接收和发送消息。我的目标是稍微了解多线程,这就是我尝试这个的原因。不过谢谢你的回答!
    猜你喜欢
    • 2014-12-21
    • 2011-04-28
    • 1970-01-01
    • 1970-01-01
    • 2017-10-10
    • 2019-05-17
    • 2015-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多