【问题标题】:Socket Programming - BindException - Address already in use套接字编程 - BindException - 地址已在使用中
【发布时间】:2017-04-18 16:19:27
【问题描述】:

我了解为什么会发生绑定错误,但我已遵循我能找到的任何解决方案,但无法使其正常工作。

堆栈跟踪

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"

服务器代码

@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();}  
}
  • 每次服务器获得传入连接时,它都会创建一个新线程来完成这项工作。

服务器工作者

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

客户

/*-- Send a message to a different airport --*/
public void sendMessage(int port, String message){
        new Thread(new ClientWorker(port, message)).start();
}
  • 客户端(机场对象)在想要与不同机场通信时调用此消息。将创建一个新线程来处理该工作。

客户工作者

@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);}   
}
  • 错误追溯到这里——'Socket s = new Socket("localhost", port);'

备注

  • 所有工作都在同一台机器上完成。
  • 每秒可以发送数百条消息。
  • 所有客户端都在并行运行。
  • 客户端可能必须(非​​常)快速地连续发送多条消息。

我以为我正在为每条消息建立一个新的连接,但我一定是误会了什么。

【问题讨论】:

  • 该错误不应该来自客户端。包括完整的堆栈跟踪。
  • 我想这是你所说的完整轨迹,我并没有从中收集到任何东西,添加到 OP 中。
  • 此错误是否发生在 Windows 中?

标签: java multithreading sockets ports


【解决方案1】:

您正在使用Socket socket = listener.accept();,您需要在使用到服务器代码后关闭socket。 `

【讨论】:

  • 我在 Server Worker 结束时关闭了套接字?这不正确吗?
【解决方案2】:

您可能已经用尽了可以同时建立的客户端连接数;在那种情况下滥用ServerSocket#setReuseAddress() 可能不是一个好主意。

我以为我是在为每条消息建立新的连接,但我一定是误会了什么。

你是 - 这就是问题 :) 考虑某种连接池来重用现有连接,而不是一次旋转数千个连接(如果您的客户端和服务器跨主机,甚至建立连接的开销也可能很快成为像这样的设置中的瓶颈)。

【讨论】:

  • 谢谢,我不认为我在建立大量的连接,但我在循环中添加了一个延迟以尝试让它恢复,它现在似乎正在工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多