2009-08-27 30 views
31

Nếu tôi chỉ VIẾT vào một ổ cắm trên luồng đầu ra, nó có chặn không? Chỉ đọc có thể chặn, phải không? Ai đó nói với tôi viết có thể chặn nhưng tôi chỉ thấy một tính năng thời gian chờ cho phương pháp đọc của một ổ cắm - Socket.setSoTimeout().Luồng socket/đầu ra java viết: chúng có chặn không?

Điều đó không có ý nghĩa với tôi rằng việc viết có thể chặn.

+0

Thực tế là có không phải là một tính năng thời gian chờ bản thân nó không là một dấu hiệu cho thấy nó không chặn. Một dấu hiệu cho thấy nó là thiếu giá trị trả về: nếu nó không chặn, tại sao nó không trả về số byte thực sự được viết? Một dấu hiệu khác được đưa ra bởi chỉ cần thử nó. – EJP

Trả lời

45

Một ghi trên Ổ cắm cũng có thể chặn, đặc biệt nếu đó là một Ổ cắm TCP. Hệ điều hành sẽ chỉ đệm một lượng dữ liệu chưa được truyền đi (hoặc được truyền nhưng chưa được nhận). Nếu bạn viết nội dung nhanh hơn ứng dụng từ xa có thể đọc nó, cuối cùng ổ cắm sẽ sao lưu và các cuộc gọi write của bạn sẽ bị chặn.

Đối phó với những câu hỏi của followup:

Vậy là có một cơ chế để thiết lập một thời gian chờ cho việc này? Tôi không chắc chắn hành vi của mà nó có ... có thể vứt bỏ dữ liệu nếu bộ đệm đầy? Hoặc có thể xóa dữ liệu cũ hơn trong bộ đệm?

Không có cơ chế để đặt thời gian chờ ghi trên java.net.Socket. Có phương thức Socket.setSoTimeout(), nhưng nó ảnh hưởng đến các cuộc gọi accept()read() cuộc gọi ... và không phải write() cuộc gọi. Rõ ràng, bạn có thể ghi thời gian chờ nếu bạn sử dụng NIO, chế độ không chặn và Bộ chọn, nhưng điều này không hữu ích như bạn có thể tưởng tượng.

Ngăn xếp TCP được triển khai đúng cách không loại bỏ dữ liệu đệm trừ khi kết nối được đóng. Tuy nhiên, khi bạn nhận được một thời gian chờ ghi, nó là không chắc chắn liệu dữ liệu hiện đang trong bộ đệm cấp độ hệ điều hành đã được nhận bởi đầu kia ... hay không. Vấn đề khác là bạn không biết bao nhiêu dữ liệu từ write cuối cùng của bạn đã thực sự được chuyển sang bộ đệm ngăn xếp TCP cấp hệ điều hành. Không có một số giao thức cấp ứng dụng để đồng bộ hóa lại luồng *, điều duy nhất an toàn để thực hiện sau khi hết thời gian chờ trên write là tắt kết nối.

Ngược lại, nếu bạn sử dụng ổ cắm UDP, các cuộc gọi write() sẽ không chặn trong bất kỳ khoảng thời gian đáng kể nào. Nhưng nhược điểm là nếu có vấn đề về mạng hoặc ứng dụng từ xa không được cập nhật, tin nhắn sẽ bị xóa trên sàn mà không có thông báo kết thúc. Ngoài ra, bạn có thể thấy rằng các thư đôi khi được gửi tới ứng dụng từ xa không đúng thứ tự. Nó sẽ tùy thuộc vào bạn (nhà phát triển) để đối phó với những vấn đề này.

* Về mặt lý thuyết có thể thực hiện điều này, nhưng đối với hầu hết các ứng dụng, sẽ không có ý nghĩa để thực hiện thêm cơ chế đồng bộ hóa trên đầu luồng TCP/IP đã tin cậy (tới một điểm). Và nếu nó có ý nghĩa, bạn cũng sẽ cần phải đối phó với khả năng kết nối đóng lại ... vì vậy nó sẽ đơn giản hơn để giả sử nó đóng.

+0

Vì vậy, có một cơ chế để thiết lập một thời gian chờ cho điều này? Tôi không chắc chắn về hành vi của nó ... có thể vứt bỏ dữ liệu nếu các bộ đệm đầy? Hoặc có thể xóa dữ liệu cũ hơn trong bộ đệm? – jbu

+0

Có cách nào để tái tạo điều này để thử nghiệm không? Tôi muốn làm cho ứng dụng của tôi có thể hồi phục từ điều này. cho điều này tôi cần kiểm tra – Zamir

+0

AFAIK, không có cách nào chung. Nhưng tùy thuộc vào bản chất của ứng dụng của bạn (ví dụ như những gì nó đang nói đến) có rất nhiều cách. Đặt câu hỏi mới ... và cụ thể. –

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