2011-01-26 30 views
5

Tôi sẽ xem tài liệu và howtos tôi đang tìm kiếm về cách sử dụng thích hợp của IO :: Chọn về truyền thông socket mạng. Tôi nghĩ rằng tôi đã có đầu của tôi quấn quanh hầu hết của nó.Làm cách nào để thực hiện đúng IO :: Chọn xử lý lỗi?

Tuy nhiên, tôi vẫn bị mờ về xử lý lỗi thích hợp. Nói rằng tôi đã có một cái gì đó tương tự như mã sau chạy bên trong một đối tượng. Có, tôi nhận ra nó lộn xộn, tôi nên tích hợp IO :: Chọn vào đối tượng và không phải là ổ cắm fh chính nó, tôi không nên tạo lại IO :: Chọn mỗi lần thông qua vòng lặp, tôi đang lặp qua những gì chỉ có thể bao giờ là một filehandle trả về duy nhất, vv Tuy nhiên, điều này giữ cho ví dụ đơn giản.

Đây chỉ là ứng dụng khách kết nối với máy chủ, nhưng tôi muốn có thể xử lý đúng các lỗi cấp mạng như mất gói.

Chỉnh sửa: $self->sock() chỉ trả về một IO đã mở :: Ổ cắm :: Ổ cắm INET.

sub read { 
    my $self = shift; 
    my($length) = @_; ### Number of bytes to read from the socket 

    my $ret; 

    while (length($ret) < $length) { 
     my $str; 

     use IO::Select; 
     my $sel = IO::Select->new($self->sock()); 

     if (my @ready = $sel->can_read(5)) { ### 5 sec timeout 
      for my $fh (@ready) { 
      my $recv_ret = $fh->recv($str, $length - length($ret)); 
      if (!defined $recv_ret) { 
       MyApp::Exception->throw(
       message => "connection closed by remote host: $!", 
      ); 
      } 
      } 
     } 
     else { 
      ### Nothing ready... we timed out! 
      MyApp::Exception->throw(
        message => "no response from remote host", 
      ); 
     } 
     $ret .= $str; 
     } 

     return $ret; 
} 
  • Tôi có cần phải được kiểm tra sự trở lại từ recv, hoặc những sai sót đó sẽ ảnh hưởng đến nó sẽ được hiển thị trong IO :: Chọn đối tượng?
  • Tôi có xử lý đúng thời gian chờ hoặc logic của tôi có được thiết lập sai không?
  • IO :: Ổ cắm đề cập đến một ngoại lệ hiện có trên một tập tin ổ cắm, vì lỗi ngoài dải và các vấn đề khác. Tôi có nên kiểm tra điều này trong trường hợp hết thời gian chờ không? Làm sao? Hoặc là nó không quan trọng và OK để bỏ qua?
  • Có trường hợp ngoại lệ nào khác mà tôi phải xử lý cho hành vi thích hợp không?
+0

Tại sao bạn mong đợi một "độ dài tối thiểu" của dữ liệu để thu thập? Và nếu sock() trả về một mảng các tệp thủ công, bạn sẽ nhận được kết hợp các phản hồi từ tất cả các socket theo thứ tự ngẫu nhiên - đó có phải là OK không? – Dallaylaen

+0

Tôi mong đợi một độ dài tối thiểu của dữ liệu để thu thập vì máy chủ từ xa này đang phản hồi lệnh. Thay vì thay đổi toàn bộ bộ đệm, tôi chỉ chuyển một byte để xác định độ dài của đoạn sau, một đoạn, và tiếp tục cho đến khi tôi kết thúc mã hóa giao tiếp. – Oesor

Trả lời

1

1) Tôi sẽ chỉ kiểm tra trong trường hợp. Khi chọn (2), defensive programming là bạn của bạn.

2) Giả sử bạn cần 2048 byte và máy chủ từ xa gửi một byte mỗi 5 giây. Bạn vừa mới treo trong 10K giây = 3 giờ. Đó là điều bạn muốn?

Tôi sẽ sử dụng alarm 5$SIG{ALRM} = sub {$stop = 1;} để thay thế.

3 và 4) Từ kinh nghiệm của tôi, chỉ cần read() while select() thực hiện công việc nhưng tôi không thể đưa ra câu trả lời chắc chắn ở đây.

+0

2) Máy chủ từ xa sẽ gửi tất cả các byte tôi cần làm một giao tiếp duy nhất, do đó, điều này không nên áp dụng. Tôi thực sự sử dụng một báo động ném một ngoại lệ hiện nay, mà hoạt động; nó ghi lại và ném ngoại lệ thời gian chờ, nhưng tôi đang cố gắng khắc phục sự cố treo liên tục. – Oesor

+0

Nếu bạn chỉ cần một thông tin liên lạc, tại sao lại sử dụng vòng lặp? Bạn có thể nhận được '$ length' byte, hoặc bạn không. – Dallaylaen

+0

Vì nó có thể bị phân mảnh? Các gói có thể giảm xuống? Nếu tôi mong đợi 10k ký tự, tôi đợi cho đến khi socket sẵn sàng đọc, và thử đọc 10k, và tôi chỉ nhận được một gói dữ liệu 1.5k của một gói, tôi cần phải đợi xem có thêm gói và đọc lại không, don ' t tôi? – Oesor

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