2012-05-13 18 views
9

Tôi hiện đang viết mã mạng ngây thơ cho một dự án và một người bạn đã gợi ý tôi khi có khả năng gửi một gói thông tin từ máy chủ đến tất cả các máy khách trong một thời trang lặp đi lặp lại. khách hàng không phản hồi đúng cách.Có phải luồng OutputStream trong Java không? (Sockets)

Anh ấy được biết đến vì trolling vì vậy tôi đã hoài nghi khi thực hiện một chủ đề thứ cấp mà bây giờ chịu trách nhiệm gửi dữ liệu cho một khách hàng, có một hàng đợi Server chỉ cần thêm các gói trên đó rồi đọc bởi chủ đề để gửi dữ liệu.

Câu hỏi tôi có sau khi suy nghĩ về thời tiết hay không là OutputStream của Java Socket thực sự xếp hàng thứ mà anh ta muốn gửi, do đó loại bỏ nhu cầu hàng đợi trước. Khả năng xảy ra sự cố dữ dội chỉ xảy ra khi Máy chủ đang chặn miễn là anh ta không nhận được phản hồi từ máy khách mà đối tượng đã gửi đã được nhận.

Cảm ơn.

+0

Tôi đã gặp phải sự cố tương tự nếu tôi cố gắng lấy dòng ouput hoặc input trong chức năng chạy của Thread.Vấn đề với việc chặn (cho cả getInputStream và getOutputStream) của socket là bởi vì nó đang ở trong hàm run ... giải pháp có vẻ là đặt nó vào hàm tạo, lưu biến và sau đó tham chiếu biến trong khi chạy. – Zimm3r

Trả lời

4

Tất nhiên, khi bạn ghi vào ổ cắm, ghi này được đệm. Đối tượng Socket có phương thức setSendBufferSize() để thiết lập kích thước bộ đệm này. Nếu ghi của bạn có thể được lưu trữ trong bộ đệm này, thì tất nhiên, bạn có thể lặp lại ngay trên ổ cắm sau đây. Nếu không, bộ đệm này cần phải được xả sạch cho máy khách ngay lập tức. Vì vậy, trong quá trình xả, bạn sẽ bị chặn. Nếu bạn muốn tránh bị chặn trong khi xả bộ đệm, bạn phải sử dụng SocketChannel trong I/O không chặn. Dù sao, tùy chọn tốt nhất để ghi vào nhiều socket đồng thời, là quản lý từng socket với một luồng khác nhau, để tất cả các ghi có thể được thực hiện cùng một lúc.

+5

"Nếu không, bộ đệm này cần được xả cho máy khách ngay lập tức" không phải là cách chính xác. Bộ đệm được ghi vào mạng tất cả các thời gian, không đồng bộ, nhưng nó không thể được gửi cho đến khi có phòng trong bộ đệm nhận của người nhận. Nếu đồng đẳng không đọc, hoặc đang đọc chậm, bộ đệm nhận của anh ta sẽ lấp đầy, vì vậy bộ đệm gửi của bạn sẽ lấp đầy, vì vậy các lần ghi tiếp theo của bạn sẽ bị chặn. – EJP

+0

Mặc dù bài viết của Tomasz là một ví dụ tốt hơn nhưng đây chính xác là những gì tôi đang tìm kiếm về giải thích EJP. Cảm ơn nhiều. – salbeira

8

Bạn của bạn là đúng nhưng có nhiều việc phải làm với cách thức hoạt động của giao thức . Việc đơn giản hóa các gói tin được gửi đến máy khách cần được xác nhận. Nếu máy khách không đáp ứng (không đọc dữ liệu đến, máy tính bị tải nặng, vv) máy chủ sẽ không nhận được sự xác nhận và sẽ ngừng gửi dữ liệu. Cơ chế này được tích hợp vào TCP/IP ngăn chặn một đầu của giao tiếp gửi một lượng lớn dữ liệu mà không cần đảm bảo đầu kia nhận được chúng. Đổi lại điều này tránh yêu cầu gửi lại một lượng lớn dữ liệu.

Trong Java tệp kê khai này là chặn ghi thành OutputStream. Hệ thống/ngăn xếp TCP/IP cơ bản không cho phép gửi nhiều dữ liệu hơn cho đến khi máy khách sẵn sàng nhận nó.

Bạn có thể dễ dàng kiểm tra điều này! Tôi thực hiện máy chủ đơn giản mà chấp nhận kết nối nhưng thất bại trong việc đọc dữ liệu đến:

new Thread(new Runnable() { 
    @Override 
    public void run() { 
     try { 
      final ServerSocket serverSocket = new ServerSocket(4444); 
      final Socket clientSocket = serverSocket.accept(); 
      final InputStream inputStream = clientSocket.getInputStream(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

    } 
}).start(); 

Và một khách hàng đơn giản rằng chỉ cần gửi dữ liệu nhiều như nó có thể trong 4K lô:

final Socket client = new Socket("localhost", 4444); 
final OutputStream outputStream = client.getOutputStream(); 
int packet = 0; 
while(true) { 
    System.out.println(++packet); 
    outputStream.write(new byte[1024 * 4]); 
} 

Vòng lặp client treo trên máy tính của tôi sau 95 lần lặp (số dặm của bạn có thể thay đổi). Tuy nhiên, nếu tôi đọc từ inputStream trong luồng máy chủ - vòng lặp sẽ bật và bật.

+0

Tôi đã gặp sự cố tương tự nếu tôi cố gắng lấy dòng ouput hoặc input trong chức năng chạy của một Thread. Vấn đề với việc chặn (cho cả getInputStream và getOutputStream) của socket là bởi vì nó đang ở trong hàm run ... giải pháp có vẻ là đặt nó vào hàm tạo, lưu biến và sau đó tham chiếu biến trong khi chạy. – Zimm3r

0

Một luồng đầu ra đang chặn. Nó có thể có một số đệm, nhưng điều đó không giúp bạn nhiều nếu máy chủ không bao giờ tiêu thụ byte (bất kỳ bộ đệm cố định cuối cùng sẽ điền vào). Vì vậy, bạn của bạn là đúng, bạn cần phải viết trong một chủ đề riêng biệt, hoặc sử dụng một cái gì đó cao cấp hơn, như nio.

Ở mặt đọc, bạn có thể sử dụng() để tránh bị chặn. Không có cuộc gọi phù hợp nào tồn tại ở phía ghi. Tôi ước có.

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