2009-12-16 45 views
5

Tôi có một ứng dụng client-server với một máy chủ java. Nó hoạt động khá hoàn hảo, ngoại trừ sau một thời gian dài, đột nhiên, một ổ cắm vẫn treo. Ổ cắm này là một trong số rất nhiều, phần còn lại dường như vẫn hoạt động tốt, nhưng một khi nó được đưa vào socket, máy chủ chỉ đơn giản là không đi qua đường gửi. Đây là những mảnh có liên quan của mã:Java - Ổ cắm treo lạ?

Socket socket; // A normal socket 
out = new PrintWriter(socket.getOutputStream(), true); // The outstream 
out.println(msg + "\0"); // This command is used to send stuff, msg is a String 

Không có ngoại lệ được ném, việc áp dụng dây chuyền đơn giản dường như không vượt qua dòng:

out.println(msg + "\0"); 

tôi biết rằng String là một tốt một, gây ra 4 hoặc 5 ổ cắm khác trước khi có thể gửi nó tốt. Cũng lưu ý rằng, theo như tôi biết, ổ cắm này có thể gửi hàng trăm tin nhắn tốt trước khi nó đột nhiên bị treo. Có ai có một đầu mối những loại lỗi tôi nên tìm kiếm?

+0

Bạn đang chạy hệ điều hành nào? Bạn đang nói chuyện với một cái gì đó gần đó hay xa? – bmargulies

+1

kiểm tra kích thước hàng gửi/nhận? Âm thanh như một vấn đề tôi đã trải qua gần đây, nơi bộ đệm đầy và gây ra phần còn lại của kết nối để treo. –

+0

Bạn có chắc chắn rằng ổ cắm có một đầu đọc tích cực và nó không chỉ là bộ đệm đầy? – rsp

Trả lời

5

Có nhiều thứ có thể gây ra điều này, nhưng có vẻ như bạn có thể bị ép lại ở cấp TCP.

Thông thường, khi bạn gửi dữ liệu trên ổ cắm, nó chỉ đơn giản là đệm và cuộc gọi gửi (trong trường hợp của bạn, println()flush()) có thể trở lại trước khi dữ liệu thực sự được gửi đến mạng. Nó có thể là tất cả các ghi trước đây của bạn trên ổ cắm này đã được đệm vào địa phương SO_SNDBUF và bạn chỉ cần điền nó lên.

(1) Bạn có thể theo dõi điều này bằng cách sử dụng tcpdump hoặc Wireshark và tìm kết nối chính xác đang treo (tôi biết điều này gặp khó khăn với nhiều kết nối)? Kiểm tra kích thước cửa sổ TCP tại thời điểm chương trình của bạn bị treo sẽ cho bạn biết thêm về việc liệu bạn có đang chặn chính Java hay ở cấp độ mạng hay không.

(2) Đổ ngăn xếp và đăng lên đây. Ổ cắm Java có khóa bên trong để ngăn không cho hai luồng ghi vào cùng một lúc. Bạn có chắc chắn chỉ có một thread đang truy cập vào socket đó tại thời điểm bạn thử viết không?

Bạn chắc chắn muốn thử làm một

$ jstack <PID> 

khi nó bị đóng băng để xem chính xác nơi nó treo, và nếu các chủ đề văn đang nỗ lực để có được bất kỳ ổ khóa.

3

Socket đối tượng OutputStream sẽ chặn khi viết dưới cùng điều kiện mà lệnh gọi send() bên dưới sẽ chặn: khi bộ đệm ổ cắm cục bộ đầy. Rằng nó vẫn bị chặn chỉ ra rằng bộ đệm đầu ra không thể làm trống, mà lần lượt chỉ ra rằng bộ đệm đọc ở đầu kia của kết nối đã đầy, và ứng dụng xử lý đầu kia của kết nối không đọc dữ liệu đã đến .