פתרון צינורות ופרוטוקול מקומי¶
נוסיף פונקציית קריאה של מספר little endian, ונפעיל אותה רק לאחר שנבדק גודל המסגרת:
std::uint64_t get(const std::array<std::byte, 24>& bytes,
std::size_t offset, unsigned width) {
std::uint64_t value = 0;
for (unsigned i = 0; i < width; ++i)
value |= std::uint64_t(std::to_integer<unsigned char>(
bytes[offset + i])) << (i * 8);
return value;
}
הפונקציה משתלבת בלקוח ההרצאה. החוזה הפנימי שלה דורש ש־offset ועוד width לא יעברו עשרים וארבע, וש־width לא יעבור שמונה. כאן הקריאות משתמשות בקבועים של הפורמט; אם חושפים את הפונקציה לקלט כללי, מוסיפים בדיקות מפורשות.
הסטטוס נמצא בבתים ארבע עד שבע, מזהה הבקשה בבתים שמונה עד חמש עשרה, הערך בבתים שש עשרה עד תשע עשרה והדגלים בבתים עשרים עד עשרים ושלוש. הצלחת put בפרויקט מסומנת בסטטוס אפס ובביט העמידות. סטטוס של מפתח חסר מובחן מערך אפס תקין.
מסגרת אחת ותוצאה אחת¶
ב־message mode הודעה גדולה מן ה־buffer יכולה להחזיר ERROR_MORE_DATA. בפרוטוקול הקבוע אנחנו דוחים את החיבור; אין ניסיון לפרש את עשרים וארבעה הבתים הראשונים כהודעה תקינה ולהתעלם מהשאר. הודעה קצרה נדחית באותה דרך.
מזהה שגוי בתשובה הוא הפרת פרוטוקול גם כאשר הערך נראה סביר. הלקוח צריך לקשור תוצאה לבקשה מסוימת, במיוחד אם בעתיד יהיו כמה בקשות פעילות. סטטוס לא מוכר ודגלים שאינם מוגדרים צריכים לקבל מדיניות מפורשת לפי גרסת הפרוטוקול.
תשובה שאבדה¶
אחרי כתיבה מוצלחת ייתכן שהשרת כבר כתב ליומן וביצע flush. חריגה ממועד ההמתנה לקריאת התשובה אינו מחזיר את העולם למצב הקודם. ניסיון חוזר עם אותו מזהה ואותו תוכן מאפשר לשרת להחזיר תוצאה שמורה. שימוש באותו מזהה עם תוכן אחר צריך להידחות, ושימוש במזהה חדש מציין פעולה חדשה.
הלקוח צריך לשמור את מזהה הבקשה כל עוד תוצאתה אינה ידועה. בפרויקט נשמור גם בצד השרת את ההתאמה בין מזהה לתוכן ולתוצאה, כדי שההבטחה תשרוד אתחול ולא תהיה רק cache זמני.