לדלג לתוכן

פתרון התקדמות חלקית

הטיפוס הבא מצטרף לקובץ ההרצאה ומחזיק את ההתקדמות של הודעה אחת. הוא מעדכן את המיקום גם כאשר פונקציית הכתיבה מחזירה שגיאה.

struct Pending { bytes: Vec<u8>, done: usize }
impl Pending {
    fn advance<W: Write>(&mut self, writer: &mut W) -> io::Result<bool> {
        match write_progress(writer, &self.bytes[self.done..]) {
            Ok(count) => { self.done += count; Ok(true) }
            Err((count, error)) => {
                self.done += count;
                if error.kind() == io::ErrorKind::WouldBlock { Ok(false) }
                else { Err(error) }
            }
        }
    }
}

הבדיקה המרכזית מפעילה advance שוב אחרי חסימה ומשווה את כל הבאפר ביעד, ולא רק את אורכו. שתי הודעות שונות יכולות להיות באותו אורך, ושכפול קידומת יכול להסתתר אם בודקים רק מונה הצלחות.

המערכת המקומית אינה יודעת אם שרת ביצע פעולה לפני שהחיבור נותק. אפילו אם כל הבייטים נשלחו פעם אחת, הלקוח עשוי להפעיל מחדש את הבקשה אחרי חוסר תשובה. מניעת ביצוע כפול היא חוזה של הפרוטוקול, למשל באמצעות מזהה ייחודי ורישום תוצאה בצד השרת.