2011-11-08 17 views
14

Đây là một máy chủ TCP đơn giản. Làm thế nào tôi có thể đóng socket khi chương trình kết thúc? Tôi đã sử dụng thử/cuối cùng và cố gắng đóng ổ cắm. Nhưng nó không chạy khối cuối cùng khi tôi thoát khỏi chương trình.Làm cách nào để đóng ổ cắm theo cách phù hợp?

Bất kỳ ai cũng có thể có ý tưởng về cách đóng ổ cắm theo cách phù hợp?

try { 
     socket = new ServerSocket(port); 
     System.out.println("Server is starting on port " + port + " ..."); 
    }catch (IOException e){ 
     System.out.println("Error on socket creation!"); 
    } 

    Socket connectionSocket = null; 
    try{ 
     while(true){    
      try{ 
       connectionSocket = socket.accept(); 
       Thread t = new Thread(new ClientConnection(connectionSocket)); 
       t.start(); 
      }catch (IOException e) { 
       System.out.println("Error on accept socket!"); 
      } 
     } 
    }finally{ 
     this.socket.close(); 
     System.out.println("The server is shut down!"); 
    } 
+1

gọi các ổ cắm 'close() 'phương pháp trong khối finally của bạn, hoặc bây giờ với java 7 bạn có thể sử dụng các khối try-với-nguồn lực, và nó sẽ đóng chúng cho bạn. http://www.javacodegeeks.com/2011/07/java-7-try-with-resources-explained.html –

+0

Bạn cũng cần kiểm tra rỗng trước khi gọi 'close()' trong trường hợp hàm tạo 'ServerSocket' ném một ngoại lệ. – unholysampler

+0

@Kit Ho, Đơn đăng ký bị chấm dứt như thế nào? – mre

Trả lời

0

Kết quả cuối cùng không được chạy? Có lẽ là while (true) nên được thay thế bằng một cái gì đó giống như

while (!shutdownRequested) 

cách khác bạn có thể tạo một cái móc tắt máy để xử lý các ổ cắm gần

+0

một lưu ý nit-picky, hãy kiểm tra Javadoc. Bạn muốn đóng, không phá hủy. http://download.oracle.com/javase/6/docs/api/java/net/ServerSocket.html –

+0

không nhận được nó, bạn có thể xây dựng thêm không? –

+0

bạn có thể thử, thông báo "Máy chủ bị tắt sẽ không in!" –

0

Vâng, làm thế nào để bạn "thoát" chương trình? finally sẽ được thực hiện nếu một ngoại lệ sẽ được ném hoặc nếu khối thử kết thúc thực hiện theo cách "bình thường" nhưng tôi nghĩ rằng có thể "khó" do while(true) của bạn.

Để đóng ổ cắm, bạn nên sử dụng socket.close() và tôi khuyên bạn không nên dựa vào chức năng hủy.

10

Sau khi tạo ServerSocket của bạn, bạn có thể thêm một để đóng nó lại về việc chấm dứt JVM, một cái gì đó như thế này:

Runtime.getRuntime().addShutdownHook(new Thread(){public void run(){ 
    try { 
     socket.close(); 
     System.out.println("The server is shut down!"); 
    } catch (IOException e) { /* failed */ } 
}}); 

Gọi ServerSocket#close sẽ chấm dứt chặn ServerSocket.accept cuộc gọi, làm cho nó ném một SocketException. Tuy nhiên, lưu ý rằng việc xử lý IOException hiện tại của bạn trong vòng lặp while có nghĩa là bạn sẽ nhập lại vòng lặp while để thử chấp nhận trên một socket đã đóng. JVM sẽ vẫn chấm dứt, nhưng nó hơi lộn xộn một chút.

Móc tắt máy không chạy nếu bạn chấm dứt một ứng dụng bảng điều khiển trong Eclipse (ít nhất là trên Windows). Nhưng chúng chạy nếu bạn CTRL-C Java trong một giao diện điều khiển bình thường. Để chúng chạy, bạn cần JVM được kết thúc bình thường, ví dụ: SIGINT hoặc SIGTERM thay vì SIGKILL (kill -9).

Một chương trình đơn giản mà bạn có thể thực hiện trong Eclipse hoặc bảng điều khiển sẽ trình bày điều này.

public class Test implements Runnable { 

    public static void main(String[] args) throws InterruptedException { 
    final Test test = new Test(); 
    Runtime.getRuntime().addShutdownHook(new Thread(){public void run(){ 
     test.shutdown(); 
    }}); 
    Thread t = new Thread(test); 
    t.start(); 
    } 

    public void run() { 
    synchronized(this) { 
     try { 
     System.err.println("running"); 
     wait(); 
     } catch (InterruptedException e) {} 
    } 
    } 

    public void shutdown() { 
    System.err.println("shutdown"); 
    } 
} 
+1

Có phải 'ShutDownHook's ALWAYS được thực thi không? Có thực hành thông thường và an toàn để dựa vào chúng? – Gevorg

+1

@Gevorg Như javadoc đã nói, ShutdownHooks được chạy bởi JVM trước khi thoát khi nó bị chấm dứt bình thường. Nếu bạn "giết -9" một quá trình Java, họ sẽ không. Tôi đã thấy các móc tắt máy được sử dụng một cách đáng tin cậy để tắt máy có trật tự các quy trình máy chủ trong phần mềm doanh nghiệp thương mại. – sudocode

+0

Vấn đề của anh ta là thoát ra khỏi vòng lặp 'accept()' vào khối 'finally {}', không phải làm gì khi anh ta đến đó. – EJP

7

Không cần trong trường hợp cụ thể của bạn, hệ điều hành sẽ đóng tất cả các cổng TCP cho bạn khi chương trình thoát.

+4

Bạn nói đúng rằng hệ điều hành sẽ đóng tất cả các cổng TCP khi chương trình thoát, nhưng tôi sẽ Không nói * "Không cần" * trong mọi trường hợp. Nó phụ thuộc nếu bạn cần giải phóng cổng đã nghe trước khi thoát khỏi chương trình này (mặc dù trong trường hợp này, nó sẽ là OK vì OP muốn đóng nó khi thoát chương trình) – xav

2

Từ javadoc:

Thời gian chạy Java sẽ tự động đóng các đầu vào và đầu ra suối, các client socket, và ổ cắm máy chủ vì họ đã tạo ra trong câu lệnh try-với-tài nguyên.

Cũng

Phương pháp finalize() được gọi bởi máy ảo Java (JVM) trước khi chương trình thoát ra để cung cấp cho các chương trình một cơ hội để làm sạch và nguồn phát hành. Các chương trình đa luồng phải đóng tất cả các tệp và Các ổ cắm chúng sử dụng trước khi thoát để chúng không gặp phải sự cố đói khổ .Cuộc gọi đến server.close() trong phương thức finalize() đóng kết nối Ổ cắm được sử dụng bởi mỗi chuỗi trong chương trình này.

protected void finalize(){ 
//Objects created in run method are finalized when 
//program terminates and thread exits 
    try{ 
     server.close(); 
    } catch (IOException e) { 
     System.out.println("Could not close socket"); 
     System.exit(-1); 
    } 
    } 
Các vấn đề liên quan