Java BindException:地址已在使用,即使具有唯一端口

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23329580/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 21:57:53  来源:igfitidea点击:

BindException: Address already in use even with unique port

javalinuxeclipsesocketsport

提问by user3576868

I've asked this question yesterday and no one was able to figure out the problem I was having. So I was hoping of providing a more up to date code with the suggestions from yesterday added on. Basically, I've been trying to form a connection between a server and a client but whenever I executed the server then the client, I'd get this exception: Address already in use. The obvious answer would be to give it a new port, but even then I still get this error. I'm assuming it has something to do with my code somewhere going wrong. Can anyone spot it please? I have attached the server class and the client class.

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

This is the error I get:

这是我得到的错误:

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)

Server code:

服务器代码:

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

Client code:

客户端代码:

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

回答by Stuart Marks

You're getting the error when the server program attempts to open up a socket on port 53705 for listening. The Address already in usemessage means just that, another process on your machine is already using port 53705. It could be that some daemon process has opened this same port by coincidence, or your web browser has opened this port and is still using it.

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

Most likely, though, is that you have another instance of your server program running somewhere in the background. Check all your terminal windows, or check your IDE for tabs containing the status of running programs.

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

By the way, "unique port" is a bit misleading, as port 53705 isn't "unique" in any way, it just happens to be a port number you (or somebody) picked that you hopeisn't already in use. To get a truly unique port, use new ServerSocket(0)which will ask the system to allocate an unused port. To find out which port was assigned, use serverSocket.getLocalPort(). You might print it out, and then pass it to the client program as a command-line option.

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

回答by Marco Chiappetta

I tested your code and it works correctly (meaning: I can connect to the server, didn't test the rest). Just pay attention to the main method in MessageSendClient, there's a typo ("man" instead of "main") and the correct signature is:

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

public static void main(String[] args)

not

不是

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

Make sure the listening port is free by executing (replace YOUR_PORT with the number)

通过执行确保侦听端口是空闲的(用数字替换 YOUR_PORT)

netstat -tulpn | grep :YOUR_PORT

because that's the reason why you get that exception. If you're on Windows you might just run

因为这就是你得到那个例外的原因。如果你在 Windows 上,你可能只是运行

netstat -an

and search for the port.

并搜索端口。

回答by Yingding Wang

I think you are running into a plattform and java liberary specific issue. Please provide additional infos about your os plattform (x86/x64) and which version of jdk from which vendor are you using?

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

According to this Link http://www.oracle.com/technetwork/java/javase/7u51-relnotes-2085002.htmlAbove Oracle JDK 7u51: The default socket permissions assigned to all code including untrusted code have been changed. You can only bind sockets to the ephemeral port range on each system. Port 53705should be a save ephemeral port. But still use

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

netstat -an | grep 53705 

to double check if the port is used in linux and use netstat or tcpview for windows. You can use

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

less /proc/sys/net/ipv4/ip_local_port_range

for linux to check your ephemeral port range for linux and find

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

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

in windows to get determine your ephemeral port range. More about ephemeral range in windows can be found in how to change/view ephemeral port range in windows machines

在 Windows 中确定您的临时端口范围。有关 Windows 中临时范围的更多信息,请参阅如何更改/查看 Windows 机器中的临时端口范围

I can confirm your server code and client without the "man" -> "main" typo is running under Opensuse 12.3 with

我可以确认您的服务器代码和客户端没有“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