简体   繁体   English

套接字编程 - BindException - 地址已在使用中

[英]Socket Programming - BindException - Address already in use

I understand why the binding error occurs, but I have followed any solution I can find and cannot get it to work. 我理解为什么会发生绑定错误,但我已经遵循了我能找到的任何解决方案,并且无法使其工作。

Stack Trace 堆栈跟踪

java.net.BindException: Address already in use: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source)
at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source)
at java.net.AbstractPlainSocketImpl.connect(Unknown Source)
at java.net.PlainSocketImpl.connect(Unknown Source)
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at java.net.Socket.<init>(Unknown Source)
at socket.ClientWorker.run(ClientWorker.java:30)
at java.lang.Thread.run(Unknown Source)
Picked up JAVA_TOOL_OPTIONS: -Djava.vendor="Sun Microsystems Inc"

Server Code 服务器代码

@Override
public void run() {
    try {
        ServerSocket listener = new ServerSocket(port);        
        while (running) {   
            Socket socket = listener.accept();              
            new Thread(new ServerWorker(socket, airport)).start();     
        }
        listener.close();
    } catch (IOException e) {e.printStackTrace();}  
}
  • Each time the server gets an incoming connection, it creates a new thread to do the work. 每次服务器获得传入连接时,它都会创建一个新线程来完成工作。

Server Worker 服务器工人

@Override
public void run() {
    try {
        // Get message
        InputStream is = socket.getInputStream();
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        String number;
        number = br.readLine();

        // Add new arrival event
        String[] splitMessage = number.split(" ");
        String mode = splitMessage[2];
        int time = Integer.valueOf(splitMessage[0]);
        int airportID = Integer.valueOf(splitMessage[1]);

        if(mode.equals("STANDARD")){
            Event newEvent = new Event(EventType.ARRIVAL,time,airport); 
            airport.scheduleEvent(airportID,newEvent); 
        }

        if(mode.equals("NULL")){
            Event newEvent = new Event(EventType.NULL,time,airport); 
            airport.scheduleEvent(airportID,newEvent); 
        }

        // Close
        socket.close(); 
    } 
    catch (IOException e){e.printStackTrace();}  
}

Client 客户

/*-- Send a message to a different airport --*/
public void sendMessage(int port, String message){
        new Thread(new ClientWorker(port, message)).start();
}
  • The Client (airport object) calls this message when it want's to communicate with a different airport. 客户端(机场对象)在希望与其他机场通信时调用此消息。 A new thread is created to process the work. 创建一个新线程来处理工作。

Client Worker 客户工作者

@Override
public void run() {
    try {
        Socket s = new Socket("localhost", port);
        OutputStream os = s.getOutputStream();
        OutputStreamWriter osw = new OutputStreamWriter(os);
        BufferedWriter bw = new BufferedWriter(osw);
        String sendMessage = message + "\n";
        bw.write(sendMessage);
        bw.flush();
        s.close();
    } 
    catch (UnknownHostException e){e.printStackTrace(); System.exit(0);} 
    catch (IOException e){e.printStackTrace(); System.exit(0);}   
}
  • The error traces back to here - 'Socket s = new Socket("localhost", port);' 错误追溯到这里 - 'Socket s = new Socket(“localhost”,port);'

Notes 笔记

  • All work is done on the same machine. 所有工作都在同一台机器上完成。
  • Hundreds of messages could be sent each second. 每秒可以发送数百条消息。
  • All the clients are running in parallel. 所有客户端都并行运行。
  • The client may have to send multiple messages in (very) quick succession. 客户端可能必须(非​​常)快速连续发送多个消息。

I thought I was making a new connection per message, but I must be misunderstanding something. 我以为我是在为每条消息建立一个新连接,但我一定是在误解某些东西。

you are using Socket socket = listener.accept(); 你正在使用Socket socket = listener.accept(); you need to close socket after use into server code. 你需要在使用后关闭socket到服务器代码。 ` `

You're probably exhausting the number of client connections you can concurrently establish; 您可能会耗尽同时建立的客户端连接数量; in that case abusing ServerSocket#setReuseAddress() probably isn't a good idea. 在这种情况下滥用ServerSocket#setReuseAddress()可能不是一个好主意。

I thought I was making a new connection per message, but I must be misunderstanding something. 我以为我是在为每条消息建立一个新连接,但我一定是在误解某些东西。

You are- that's the problem :) Consider some kind of connection-pooling to reuse existing connections rather than spinning up thousands at a time (if your client and server spans across hosts, even the overhead of establishing the connection could quickly become the bottleneck in a setup like this). 你是 - 这就是问题:)考虑某种连接池来重用现有的连接而不是一次数千个(如果你的客户端和服务器跨越主机,甚至建立连接的开销很快就会成为瓶颈)像这样的设置)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM