كيفية تجنب java.net.BindException: العنوان قيد الاستخدام بالفعل




linux networking (2)

سترى أن سيتريوسادريس (صحيح) يتم استدعاؤها في وقت متأخر جدا أي بعد رمي يلقي استثناء.

يمكنك إنشاء سيرفيرسوكيت غير منضم، وجعلها قابلة لإعادة الاستخدام ومن ثم ربط ذلك، في ثلاث خطوات.

ServerSocket ss = new ServerSocket();
ss.setReuseAddress(true);
ss.bind(new InetSocketAddress(12345));

تم تشغيل ما يلي لمدة ساعة واحدة ثم أغلق:

public class Mp extends JWindow implements MouseListener, MouseMotionListener {
    public static Mp j;
  private int serverPort = 0;
  private ServerSocket serverSock = null;
  private Socket sock = null; 

  public static void main(final String[] args) throws IOException, InterruptedException, Exception {
    j = new Mp();
    j.setVisible(true);
    j.waitForConnections();
  }

  public void waitForConnections() {
    while (true) {
      try {
        sock = serverSock.accept();
        System.out.println("[TCPMediaHandler]: Accepted new socket");
        TCPMediaHandler handler = new TCPMediaHandler(sock);
        handler.start();
      } catch (IOException e) {
        e.printStackTrace(System.err);
      }
    }
  }

  public Mp() throws IOException {
    this.serverPort = 38891;
    serverSock = new ServerSocket(serverPort);
    serverSock.setReuseAddress(true);
    //serverSock.setSoTimeout(500);
    //serverSock.setSoLinger(true, 0);
    System.out.println("[TCPMediaHandler]: Server started");      
        this.v1.setBackground(Color.BLACK);
    this.v1.addMouseListener(this);
    /* Close the window */
    this.addWindowListener(new WindowAdapter() {
        public void windowClosing(WindowEvent we) {
          System.exit(0); 
        }
      });
  }

عندما أعيد تشغيل نفس الشيء فإنه يفشل مع java.net.BindException :

$ java -cp /var/tmp/dist/Mp.jar test.Mp
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:353)
    at java.net.ServerSocket.bind(ServerSocket.java:336)
    at java.net.ServerSocket.<init>(ServerSocket.java:202)
    at java.net.ServerSocket.<init>(ServerSocket.java:114)
    at test.Mp.<init>(Mp.java)
    at test.Mp.main(Mp.java)

يستغرق حوالي 3 إلى 4 دقائق قبل أن تنفذ بنجاح مرة أخرى. كيف يمكنني جعله يعمل فورا بعد اغلاق؟

متابعة:

$ netstat | grep 38891
tcp       35      0 localhost:38891         localhost:37842         CLOSE_WAIT 
tcp        0      0 localhost:34955         localhost:38891         ESTABLISHED
tcp       32      0 localhost:38891         localhost:37824         CLOSE_WAIT 
tcp        0      0 localhost:38891         localhost:34955         ESTABLISHED

$ lsof -w -n -i tcp:38891
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
xdg-scree 5254  sun   29u  IPv4 231948      0t0  TCP *:38891 (LISTEN)
xdg-scree 5355  sun   29u  IPv4 231948      0t0  TCP *:38891 (LISTEN)
xdg-scree 5455  sun   29u  IPv4 231948      0t0  TCP *:38891 (LISTEN)
telnet    7058  sun    3u  IPv4 242987      0t0  TCP 127.0.0.1:34955->127.0.0.1:38891 (ESTABLISHED)
sleep     9002  sun   29u  IPv4 231948      0t0  TCP *:38891 (LISTEN)
sleep     9005  sun   29u  IPv4 231948      0t0  TCP *:38891 (LISTEN)
sleep     9008  sun   29u  IPv4 231948      0t0  TCP *:38891 (LISTEN)

كان لي مشكلة مماثلة في أحد برامجي، ولكن انتهى الأمر حتى أنني كنت في الواقع مجرد تشغيل مثيل للبرنامج من بلدي إيد - التي لم أكن لاحظت. تحقق دائما مزدوج لا يوجد شيء قيد التشغيل في الخلفية.





tcp