【问题标题】:Java - Address already in use (net bind)Java - 地址已在使用中(网络绑定)
【发布时间】:2018-07-06 07:00:37
【问题描述】:

我知道这个问题已经被问过一百万次了,但我还没有找到像我这样的情况。我有一个简单的 java 聊天应用程序,几个月前还在工作,我又回来了,现在我遇到了问题。当我在 Eclipse 中运行 server.java 时,一切正常。当我之后运行 client.java 文件时,我得到以下信息:

Exception in thread "main" java.net.BindException: Address already in use: NET_Bind
    at java.base/java.net.DualStackPlainSocketImpl.bind0(Native Method)
    at java.base/java.net.DualStackPlainSocketImpl.socketBind(Unknown Source)
    at java.base/java.net.AbstractPlainSocketImpl.bind(Unknown Source)
    at java.base/java.net.PlainSocketImpl.bind(Unknown Source)
    at java.base/java.net.ServerSocket.bind(Unknown Source)
    at java.base/java.net.ServerSocket.<init>(Unknown Source)
    at java.base/java.net.ServerSocket.<init>(Unknown Source)
    at chat.Server.main(Server.java:18)

我已经终止了 eclipse 中的所有启动,在命令提示符中找到了 PID 并将其杀死,尝试更改端口号,但每次尝试运行我的程序时,我仍然得到仍在使用的地址。我还尝试在命令提示符下运行 netstat -a 命令来查找正在使用的端口号,但我没有尝试过。

Server.java(包含服务器代码以及客户端处理程序类):

public class Server 
{
    //vector to store active clients, static so threads share the vector of clients
    static Vector<ClientHandler> activeUsers = new Vector<>();

    public static void main(String[] args) throws IOException 
    {
        ServerSocket serverSocket = new ServerSocket(1234); //server is listening on port 1234
        Socket s;   
        while (true) //infinite loop for getting client request
        {
            s = serverSocket.accept(); //accept the incoming request

            //obtain input and output streams
            DataInputStream dis = new DataInputStream(s.getInputStream());
            DataOutputStream dos = new DataOutputStream(s.getOutputStream());

            String username = dis.readUTF(); //username is first thing sent from the client for naming
            ClientHandler newClient = new ClientHandler(s,username , dis, dos); //create a new handler object for handling this client

            //notify currently connected users that a new user has joined
            newClient.notifyUsers(activeUsers, " has joined the server!");

            Thread t = new Thread(newClient); //create a new Thread with this object.
            activeUsers.add(newClient); //add this client to active clients list
            t.start(); //start the thread.
        }//end while


    }//end main
}//end class Server

class ClientHandler implements Runnable 
{
    private String name;
    DataInputStream dis;
    DataOutputStream dos;
    Socket socket;
    boolean isloggedin;


    public ClientHandler(Socket socket, String name, DataInputStream dis, DataOutputStream dos) 
    {
        this.dis = dis; //data input stream
        this.dos = dos; //data output stream
        this.name = name; //client name
        this.socket = socket; //socket
        this.isloggedin=true; //handler is being created so user is logged in
    }
}

Client.java:

public class Client extends JFrame implements ActionListener
{
    DataInputStream dis = null;
    DataOutputStream dos = null;
    final static int ServerPort = 1234;
    JButton     sendMessage;
    JTextField  messageBox;
    JTextArea   chatBox;
    JButton     logoutButton;
    JButton     activeUsersButton;
    JFrame      newFrame    = new JFrame(".Chat");
    String username;
    Socket s = null;


    public Client(String user)
    {

        this.username = user;
    }

    public void start() throws UnknownHostException, IOException 
    {
        newFrame.setTitle("chat - " + username);

        InetAddress ip = InetAddress.getByName("localhost");

        //establish the connection to the server
        s = new Socket(ip, ServerPort);

        //obtaining input and out streams
        dis = new DataInputStream(s.getInputStream());
        dos =  new DataOutputStream(s.getOutputStream());

        dos.writeUTF(username);

        //readMessage thread
        Thread readMessage = new Thread(new Runnable() 
        {
            @Override
            public void run() 
            {
                while (dos != null && dis != null) {
                    try 
                    {
                        //read the message sent to this client
                        String msg = dis.readUTF();
                        System.out.println(msg);
                        chatBox.append(msg);
                    } //end try
                    catch (IOException e) 
                    {

                        e.printStackTrace();
                    }//end catch
                }//end while
            }//end run
        });
        display();
        readMessage.start();
    }


    //not sure what this needs to do? just to satisfy an error
    @Override
    public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub
         Object obj = e.getSource();
           if(obj == sendMessage){ 
                String msg = messageBox.getText();
                try {
                    dos.writeUTF(msg);
                    chatBox.append(username + ": " + msg + "\n"); //place what the user sent in the text box
                    messageBox.setText(""); 
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
           } 
           else{}
    }
}

我省略了按钮代码作为它在套接字上的唯一发送/接收消息以及 UI 代码。

【问题讨论】:

  • 问题在于,当您运行客户端时,它会连接到服务器,然后您的服务器应用程序会尝试在同一端口上创建第二个套接字并收到错误消息。尝试移动 Socket ;在循环内部?
  • @Veselin Davidov,刚刚尝试过,但仍然遇到同样的错误。服务器文件中的 Socket S 是客户端连接到服务器的套接字,存储在 ClientHandler 对象中,我没有创建一个新的。这一切正常,我没有改变任何东西,所以我现在只是处于静止状态。
  • 在 Linux 上,您可以使用 netstat、lsof 或 nmap 找出正在使用的端口。
  • @StephenC 抱歉,编辑添加我正在命令提示符中运行 netstat -a 命令以查找当前使用的端口,并且在运行之前我尝试的端口都没有实际使用。
  • @VeselinDavidov 你在说什么?你读过堆栈跟踪吗?

标签: java sockets networking port


【解决方案1】:

当你启动你的服务器时,有些东西已经在监听 1234 端口:可能是它的先前实例;或者可能在 TIME_WAIT 中仍然有一个套接字。用 SO_REUSEADDR 试试,这样:

ServerSocket serverSocket = new ServerSocket();
serverSocket.setReuseAddress(true);
serverSocket.bind(new InetSocketAddress(1234));

NB 你还有一个问题。您忽略了流的结束。鉴于您正在调用readUTF(),您需要捕获EOFException 并退出循环并在抛出套接字时关闭它。 EOS 不会神奇地将输入或输出流设为 null。

【讨论】:

  • 他说他检查了该软件的先前实例并杀死了所有实例。他还说,当他运行客户端而不是服务器时,他遇到了问题——服务器最初运行良好。这就是为什么我怀疑当他第二次尝试打开 Socket 时问题会出现 - 在他刚刚启动的客户端连接之后。
  • @VeselinDavidov 那么为什么accept() 没有出现在堆栈跟踪中呢?为什么会出现ServerSocket 构造函数确实?第二次打开套接字是什么废话?你似乎在暗示他不应该打电话。 accept() 在所有。
  • @EJP - 抱歉回复晚了。刚刚将我的服务器套接字创建更改为您的建议,但仍然收到相同的错误。您的意思是使套接字而不是服务器套接字为空吗?当收到注销事件时,我正在 ClientHandler 中处理它,只是没有包含那部分代码。
  • 我的意思不是让任何东西为空。我的意思是关闭套接字,或者输入流,或者最好的输出流。
  • @EJP 当用户注销时,我将在客户端处理程序类中关闭它们,但我没有让它通过绑定 Server.java 文件中的套接字。当我在服务器文件已经运行后尝试运行客户端文件时,出现地址已在使用错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-18
  • 2011-01-09
  • 2018-04-01
  • 1970-01-01
相关资源
最近更新 更多