2012-01-09 11 views

Trả lời

9

Bạn có thể yêu cầu chặn recv đó cho đến khi tất cả dữ liệu được nhận, với cờ MSG_WAITALL. Tuy nhiên, nếu tín hiệu đến, cuộc gọi hệ thống đã thực hiện một số công việc (tức là nhận một phần dữ liệu) không thể tự động khởi động lại để nhận phần còn lại. Như vậy, ngay cả với MSG_WAITALL, có những trường hợp mà cuộc gọi recv có thể trở lại trước khi bộ đệm đầy, và bạn phải sẵn sàng để xử lý những trường hợp này. Với điều này, nhiều người chỉ đơn giản là chọn vòng lặp và không bận tâm với những lá cờ ít được biết đến như MSG_WAITALL.

Đối với lý do tại sao đây là trường hợp theo mặc định, có một vài lý do mà tôi suy nghĩ:

  • thường bạn muốn để nhận phần đọc. Ví dụ, nếu bạn đang từng bước hiển thị dữ liệu như nó đi vào, hoặc nếu bạn đang proxy nó vào một nơi khác, hoặc nếu dữ liệu quá lớn, bạn không thể đệm toàn bộ điều trong bộ nhớ cùng một lúc. Sau khi tất cả, nếu bạn chỉ ngay lập tức bằng văn bản cho một tập tin, bạn có quan tâm rằng bạn chia nó trên 200 viết thay vì, nói rằng, 150?
  • Đôi khi bạn thậm chí không biết bạn cần bao nhiêu dữ liệu ngay từ đầu. Xem xét giao thức telnet, phổ biến vào khoảng thời gian khi API ổ cắm BSD được thiết kế. Thông thường, bạn sẽ nhận được một số lượng byte tại một thời điểm, không có trường độ dài cho biết số lượng dữ liệu mong đợi và hơn thế nữa, bạn cần hiển thị dữ liệu đó ngay lập tức. Nó không có ý nghĩa để chặn cho đến khi bạn điền vào một bộ đệm ở đây. Tương tự như vậy với các giao thức định hướng dòng như SMTP hoặc IMAP - bạn không biết lệnh này kéo dài bao lâu cho đến khi bạn nhận được tất cả.
  • recv thường được sử dụng cho các ổ cắm datagram, nơi nó nhận được một gói dữ liệu đơn, ngay cả khi nó nhỏ hơn nhiều so với bộ đệm được cung cấp. Phần mở rộng tự nhiên cho các ổ cắm trực tuyến là chỉ trả lại nhiều nhất có thể mà không cần chờ đợi.

Nhưng quan trọng nhất, vì bạn cần phải được chuẩn bị để đối phó với một bộ đệm phần nào, rất tốt để buộc mọi người đối phó với nó theo mặc định, vì vậy họ bật lên các lỗi trong vòng lặp của họ sớm - chứ không phải hơn là để chúng vẫn ẩn nấp cho đến khi một tín hiệu đến vào một thời điểm không may.

4

Trong hầu hết các trường hợp, bạn không biết có bao nhiêu dữ liệu là "tất cả dữ liệu". Ví dụ: nếu bạn đang nhận dữ liệu trong giao thức hướng dòng, một dòng có thể dài 10 byte hoặc dài 65 byte.

2

Bạn có thể thay đổi cờ ổ cắm để chặn hoặc không chặn. Trường hợp cụ thể của bạn thực sự không liên quan gì đến việc chặn hoặc không chặn.

Sẽ không có ý nghĩa khi thực hiện chức năng mạng hoạt động theo cách bạn mô tả theo mặc định - điều gì sẽ xảy ra nếu luồng không bao giờ kết thúc .. chương trình không bao giờ kết thúc? Mặt khác, điều này có vẻ không lành mạnh mặc định là hành vi.

Đọc http://www.scottklement.com/rpg/socktut/nonblocking.html để tự làm quen với chặn và không chặn IO.