הכרת המחלקות
בכדי שנוכל לכתוב תוכנה המבצעת תקשורת באמצעות פרוטוקול ה-TCP, עלינו להכיר את המחלקות בהן נשתמש. חברת מיקרוסופט בנתה שתי מחלקות אשר יקלו עלינו ביצירת תקשורת באמצעות פרוטוקול זה: TCPClient ו-TCPListener.
TCPListener – מחלקה זו מתארת מחשב מארח (שרת). כפי שצוין, בפרוטוקול ה-TCP חייבת להיווצר קישוריות מסויימת טרם נתחיל לתקשר, וקישוריות זו נוצרת כאשר המחשב המארח מקבל את הלקוח. אנו נעשה שימוש במחלקה זו באופן הבא:
- נאזין ללקוחות אשר מעוניינים להתחבר באמצעות פתיחת פורט מסויים.
- ברגע שלקוח מעוניין להתחבר, נאשר אותו ונשמור את אובייקט הלקוח שלו. אובייקט זה מאפשר לנו להאזין ולשלוח הודעות לאותו הלקוח.
- כאשר אנו רוצים לסגור את השרת, עלינו לסגור את הסוקט.
TCPClient – מחלקה זו מתארת לקוח. הלקוח מתחבר למחשב מארח (שרת) באמצעות אותו הפורט בו המחשב המארח משתמש. על הלקוח לדעת גם את כתובת ה-IP של אותו המחשב – או במילים אחרות, מה הסוקט של המחשב המרוחק. נעשה שימוש במחלקה באופן הבא:
- נתחבר למחשב המרוחק באמצעות כתובת ה-IP והפורט שלו.
- אם ההתחברות הצליחה, נוכל לשלוח ולקבל הודעות מן השרת. אם ההתחברות נכשלה, עלינו להחליט מה לעשות כעת (להציג הודעה למשתמש, לנסות להתחבר שוב וכדומה).
- בסיום השיחה (אם ההתחברות הצליחה) נסגור את הסוקט.
NetworkStream – מחלקה זו מתארת זרם של בייטים. כאשר אנו אומרים זרם של בייטים אנו מתכוונים למערך של בייטים מסודר המתאר מידע שנשלח או מתקבל. המידע אינו בהכרח מתאר חבילת מידע אחת שנשלחה – אלא יכול לתאר מספר חבילות שנשלחו. לדוגמה: כאשר השרת שולח אלינו חבילות מידע במהירות הלקוח לא יקבל כל חבילה בנפרד – החבילות יגיע ביחד על אותו הזרם. במצב כזה אנו מקבלים מערך של בייטים המתאר מספר חבילות מידע. עלינו לדעת כיצד נוכל לזהות היכן חבילה מתחילה והיכן היא מסתיימת. בכדי לעשות זאת עלינו לחשוב על הדרך בה נתאר חבילה.
להלן דוגמה לזרם המכיל מספר חבילות מידע:
125 | 255 | 0 | 169 | 210 | 5 | 1 | 33 | 95 | 20 | 50
כיצד נוכל לדעת איפה כל חבילה מתחילה ומסתיימת? לא נוכל לדעת. עלינו לתאר איך חבילה נראת בכדי שכל צד ידע כיצד לקרוא אותה. לכן עלינו ליצור פרוטוקול (מוסכמות בין שני הצדדים) בנוגע לדרך בה חבילה נראית, מעין שכבה נוספת. כך נוכל לדעת היכן מתחילה ונגמרת חבילה. כפי שציינו בתחילת המדריך, אנו הולכים לכתוב תוכנת צ'אט בין שני צדדים. אם כך, מה הם הצרכים שלנו, ומה החבילה שלנו תכיל?
החבילה שלנו תכיל שתי מחרוזות: מחרוזת המתארת את הכינוי של הצד השולח, ומחרוזת שתכיל את תוכן ההודעה. דוגמה לחבילת מידע:
איציק: שלום, מה שלומך?
הכל טוב ויפה, אבל אנחנו עדיין לא בטוחים שהכינוי ותוכן ההודעה אינם סטטיים בגודלם (אורך המחרוזת אינו קבוע), ועדיין לא נוכל לזהות מתי נגמרת החבילה בגלל שאורכה משתנה. איך נוכל לדעת את גודל החבילה? התשובה לכך היא פשוטה: נציב מספר שלם (Integer) לפני כל מחרוזת. אנו יודעים שמספרים שלמים תמיד יתפסו ארבעה בייטים (32 סיביות / 8 סיביות). לכן, תמיד נקרא את ארבעת הבייטים הראשונים וכך נוכל לדעת את אורך המחרוזת. בסופו של דבר, החבילה שלנו תראה כך:
כעת נוכל להבחין בין חבילה וחבילה בקלות רבה ונוכל לעבור לחלק המעשי של התכנות. עם זאת, מדריך זה מיועד לאנשים עם ניסיון קודם בתכנות – על כן באמצעות מדריך זה לא תלמדו כיצד לתכנת, אלא כיצד לעשות שימוש באותן שיטות אשר נלמדות במדריך זה. לאחר כל קטע קוד ינתן הסבר כללי על הנעשה, בעוד שורות הקוד עצמן יכללו בצד תיאורים קצרים.