【问题标题】:BindException: Address already in use even with unique portBindException:即使具有唯一端口,地址也已在使用中
【发布时间】:2014-06-13 07:41:06
【问题描述】:

我昨天问了这个问题,没有人能弄清楚我遇到的问题。所以我希望提供一个更新的代码,其中包含昨天添加的建议。基本上,我一直在尝试在服务器和客户端之间建立连接,但是每当我执行服务器然后客户端时,我都会得到这个异常:Address already in use。显而易见的答案是给它一个新的端口,但即便如此我仍然会收到这个错误。我假设它与我的代码某处出错有关。请问有人能看出来吗?我已经附上了服务器类和客户端类。

这是我得到的错误:

Exception in thread "main" java.net.BindException: Address already in use
    at java.net.PlainSocketImpl.socketBind(Native Method)
    at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:376)
    at java.net.ServerSocket.bind(ServerSocket.java:376)
    at java.net.ServerSocket.<init>(ServerSocket.java:237)
    at java.net.ServerSocket.<init>(ServerSocket.java:128)
    at MessageServer.main(MessageServer.java:16)

服务器代码:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.ServerSocket;
import java.net.Socket;

public class MessageServer {

    public static void main(String[] args) throws IOException {
        try {
            int port = 53705;

            ServerSocket server = new ServerSocket(port);

            while (true) {
                System.out.println("Waiting for client...");
                //server.setReuseAddress(true);
                Socket client = server.accept();

                System.out.println("Client from " + server.getInetAddress() + " connected.");
                BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
                String inputLine = in.readLine();
                System.out.println("Client said: '"+inputLine+"'");
                Writer count = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
                byte c [] = count.toString().getBytes();
                count.flush();
                count.close();
                in.close();
            } 
        } catch (IOException e) {
            System.err.println(e);
        }
    }
}

客户端代码:

import java.net.*;
import java.io.*;

public class MessageSendClient {

    public static void man(String args[]) throws IOException {
        String servername = "localhost";
        int port = 53705;
        Socket server;
        //server.setReuseAddress(true);
        try {
            server = new Socket (servername,port);

            System.out.println("Connected to " + server.getInetAddress());
            DataInputStream in = new DataInputStream(new BufferedInputStream(server.getInputStream()));

            server.close();
            byte c[] = new byte[100];
            int num = in.read(c);
            String count = new String(c);

            System.out.println("Server said: " + count);

        } catch (Exception e) { }
    }
}

【问题讨论】:

  • 您需要显示实际的堆栈跟踪并识别程序中引发异常的语句。
  • @JimGarrison 嗨,我已经使用堆栈跟踪编辑了我的帖子。你能看看我的代码哪里出错了吗?
  • 这个问题你解决了吗?

标签: java linux eclipse sockets port


【解决方案1】:

当服务器程序尝试打开端口 53705 上的套接字进行侦听时,您会收到错误消息。 Address already in use 消息意味着,您机器上的另一个进程已经在使用端口 53705。可能是某个守护进程偶然打开了相同的端口,或者您的 Web 浏览器打开了该端口并且仍在使用它。

不过,最有可能的是,您的服务器程序的另一个实例在后台某处运行。检查所有终端窗口,或检查 IDE 中包含正在运行程序状态的选项卡。

顺便说一句,“唯一端口”有点误导,因为端口 53705 在任何方面都不是“唯一”,它恰好是您(或某人)选择的一个端口号,您希望 尚未使用。要获得真正唯一的端口,请使用new ServerSocket(0),它将要求系统分配一个未使用的端口。要找出分配了哪个端口,请使用serverSocket.getLocalPort()。您可以将其打印出来,然后将其作为命令行选项传递给客户端程序。

【讨论】:

    【解决方案2】:

    我认为您遇到了特定于平台和 java 库的问题。 请提供有关您的操作系统平台 (x86/x64) 以及您使用哪个供应商的 jdk 版本的其他信息?

    根据此链接 http://www.oracle.com/technetwork/java/javase/7u51-relnotes-2085002.html Oracle JDK 7u51 以上:分配给所有代码(包括不受信任的代码)的默认套接字权限已更改。您只能将套接字绑定到每个系统上的临时端口范围。 端口 53705 应该是一个保存临时端口。 但是还是用

    netstat -an | grep 53705 
    

    仔细检查端口是否在 linux 中使用并在 windows 中使用 netstat 或 tcpview。 你可以使用

    less /proc/sys/net/ipv4/ip_local_port_range
    

    for linux 检查你的 linux 临时端口范围并找到

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters
    

    在 Windows 中确定您的临时端口范围。更多关于windows中的临时范围可以在how to change/view ephemeral port range in windows machines找到

    我可以确认您的服务器代码和客户端没有“man”->“main”错字在 Opensuse 12.3 下运行

    Java version "1.7.0_51"
    OpenJDK Runtime Environment (IcedTea 2.4.4) (suse-8.32.5-i386)
    OpenJDK Client VM (build 24.45-b08, mixed mode)
    jvm is running by an non admin user with groups: www,dialout,video,shadow,users
    

    【讨论】:

    • 这将导致安全异常,而不是 BindException。您也错误地引用了发行说明。他们说'仍然可以将套接字绑定到临时端口范围......' -1
    • @EJP:感谢您的 cmets,但新的限制是绑定临时范围之外的套接字现在需要系统安全策略中的明确许可,这意味着它是我编程之外的附加设置而环境设置。如果我不这样做,我仍然无法绑定端口,我是否也得到了由安全异常引起的 BindException?还是我错了?谢谢。
    【解决方案3】:

    我测试了你的代码,它工作正常(意思是:我可以连接到服务器,没有测试其余的)。请注意MessageSendClient中的main方法,有一个错字(“man”而不是“main”),正确的签名是:

    public static void main(String[] args)
    

    不是

    public static void main(String args[]) // Still compatible but not recommended (C-like syntax)
    

    通过执行确保监听端口空闲(将 YOUR_PORT 替换为数字)

    netstat -tulpn | grep :YOUR_PORT
    

    因为这就是您获得该异常的原因。如果你在 Windows 上,你可能只需要运行

    netstat -an
    

    然后搜索端口。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-17
      • 1970-01-01
      • 1970-01-01
      • 2019-08-21
      • 1970-01-01
      相关资源
      最近更新 更多