2010-06-12 27 views
5

Về cơ bản tôi muốn tạo một máy chủ vững chắc.Việc cần làm khi ServerSocket ném IOException và giữ máy chủ chạy

while (keepRunning.get()) { 
    try { 
     Socket clientSocket = serverSocket.accept(); 

     ... spawn a new thread to handle the client ... 
    } catch (IOException e) { 
     e.printStackTrace(); 
     // NOW WHAT? 
    } 
} 

Trong khối IOException, phải làm gì? Ổ cắm máy chủ có lỗi nên nó cần được tạo lại không? Ví dụ: chờ một vài giây và sau đó

serverSocket = ServerSocketFactory.getDefault().createServerSocket(MY_PORT); 

Tuy nhiên nếu ổ cắm máy chủ vẫn OK, thì thật đáng tiếc khi đóng và hủy tất cả các kết nối đã được chấp nhận trước đó vẫn đang giao tiếp.

EDIT: Sau một số câu trả lời, ở đây nỗ lực của tôi để đối phó với IOException. Việc triển khai sẽ đảm bảo việc duy trì máy chủ và chỉ tạo lại socket máy chủ khi cần thiết?

while (keepRunning.get()) { 
    try { 
     Socket clientSocket = serverSocket.accept(); 

     ... spawn a new thread to handle the client ... 
     bindExceptionCounter = 0; 
    } catch (IOException e) { 
     e.printStackTrace(); 

     recreateServerSocket(); 
    } 
} 

private void recreateServerSocket() { 
    while (keepRunning) { 
     try { 
      logger.info("Try to re-create Server Socket"); 
      ServerSocket socket = ServerSocketFactory.getDefault().createServerSocket(RateTableServer.RATE_EVENT_SERVER_PORT); 

      // No exception thrown, then use the new socket. 
      serverSocket = socket; 
      break; 
     } catch (BindException e) { 
      logger.info("BindException indicates that the server socket is still good.", e); 
      bindExceptionCounter++; 

      if (bindExceptionCounter < 5) { 
       break; 
      } 
     } catch (IOException e) { 
      logger.warn("Problem to re-create Server Socket", e); 
      e.printStackTrace(); 

      try { 
       Thread.sleep(30000); 
      } catch (InterruptedException ie) { 
       logger.warn(ie); 
      } 
     } 
    } 
}  

Trả lời

4

Nếu nghi ngờ, bạn có thể thử tạo lại ổ cắm máy chủ, sử dụng cùng một cổng. Nếu ổ cắm đã được đóng, thì quá trình tạo sẽ thành công và bạn có thể tiếp tục xử lý các kết nối mới. Các kết nối cũ đã biến mất, nhưng đó là ngoài tầm kiểm soát của bạn kể từ khi các ổ cắm đã được đóng lại. Nếu socket không được đóng, thì việc tạo một thể hiện mới sẽ thất bại vì cổng vẫn đang được sử dụng, mà bạn có thể bỏ qua - tức là không thay thế tham chiếu socket máy chủ hiện tại.

Nói chung, khách hàng cũng nên giả định rằng các kết nối sẽ bị hỏng và việc kết nối lại là cần thiết. Nói cách khác, nó không chỉ là máy chủ phải mạnh mẽ - khách hàng cũng nên dự đoán lỗi kết nối và kết nối lại.

+0

Nếu tạo một ổ cắm máy chủ mới, không thành công với BindException - điều này có nghĩa là 100% chắc chắn rằng ổ cắm máy chủ cũ hoàn toàn OK? – s5804

+0

Tôi không thể nói "có" cho chắc chắn, nhưng nói chung tôi sẽ giả định điều đó. Tôi cũng sẽ sử dụng một chiến lược phòng thủ. Ví dụ. nếu bạn nhận được số X thất bại gọi điện thoại chấp nhận, sau đó bạn có thể xem xét các ổ cắm máy chủ bằng cách nào đó bị hỏng, và chọn để đóng các ổ cắm máy chủ. – mdma

1

Đảm bảo bạn phân biệt giữa các số IOException khác nhau mà bạn có thể nhận được. Có ngoại lệ khi tạo kết nối không? Có ngoại lệ khi kết nối đã được thiết lập?

Mã duy nhất bạn cung cấp là dành cho accept() ing. Nói chung, IOException thường có nghĩa là lỗi trên bất kỳ lớp nào trên mạng vật lý.

Có lẽ hành vi dự phòng tốt nhất mà bạn có thể thực hiện là đợi một lượng tử thời gian nhất định và sau đó thử kết nối lại. Giả sử bạn có thể sẽ không thể kết nối lại nhiều nhất, vì bạn đã mất kết nối mạng trong thời gian dài hơn. Hãy chắc chắn rằng bạn xử lý điều này một cách duyên dáng. Như @mdma đã đề cập, điều này cũng phải được khách hàng của bạn hỗ trợ.

+0

kết nối lại - Bạn có nghĩa là tạo lại socket máy chủ? – s5804

+0

Nếu bạn bị mất ổ cắm thì có ... –

1

Bạn có thể nhận được IOException trên một accept() nếu socket máy chủ bị đóng (bạn) hoặc bạn hết tài nguyên, ví dụ: xử lý tệp. Dù bằng cách nào, không có nhiều bạn có thể làm gì về nó. Nếu serverSocket bị đóng (bạn có thể kiểm tra điều này), bạn có thể có lý do chính đáng để làm điều này. Nếu bạn hết tài nguyên, bạn sẽ phải tăng giới hạn tài nguyên của mình, yêu cầu khởi động lại ứng dụng của bạn hoặc bạn bị rò rỉ tài nguyên.

+0

Làm cách nào để kiểm tra xem ổ cắm có bị đóng không? Tôi nghĩ rằng serversocket.isClosed() luôn trả về false, bởi vì lớp cao hơn không được thông báo bởi các mức thấp hơn. Điều này có đúng không? – s5804

1

Tuy nhiên nếu ổ cắm máy chủ vẫn là OK, sau đó nó là một điều đáng tiếc để đóng nó lại và giết tất cả trước đây chấp nhận kết nối mà vẫn còn giao tiếp.

Xin lưu ý rằng đóng máy chủ sẽ KHÔNG đóng các kết nối được chấp nhận trước đó. Ngay sau khi một kết nối được chấp nhận, nó sống một cuộc sống riêng biệt, vui vẻ tại một cảng khác.

Các vấn đề liên quan