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

时间:2017-04-18 16:19:28

标签: java multithreading sockets ports

我理解为什么发生了绑定错误,但我已经按照我能找到的任何解决方案进行操作。

堆栈跟踪

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

备注

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

我想我正在为每封邮件建立一个新连接,但我一定是误解了一些东西。

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

您可能会耗尽同时建立的客户端连接数量;在这种情况下,滥用ServerSocket#setReuseAddress()可能不是一个好主意。

  

我以为我是在为每条消息建立一个新连接,但我必须误解一些事情。

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