בדף זה מובא הקוד של התוכנית ולאחריו פירוט שלו. # Echo_Server -- # Open the server listening socket # and enter the Tcl event loop # # Arguments: # port The server's port number proc Echo_Server {port} { set s [socket -server EchoAccept $port] vwait forever } # Echo_Accept -- # Accept a connection from a new client. # This is called after a new socket connection # has been created by Tcl. # # Arguments: # sock The new socket connection to the client # addr The client's IP address # port The client's port number proc EchoAccept {sock addr port} { global echo # Record the client's information puts "Accept $sock from $addr port $port" set echo(addr,$sock) [list $addr $port] # Ensure that each "puts" by the server # results in a network transmission fconfigure $sock -buffering line # Set up a callback for when the client sends data fileevent $sock readable [list Echo $sock] } # Echo -- # This procedure is called when the server # can read data from the client # # Arguments: # sock The socket connection to the client proc Echo {sock} { global echo # Check end of file or abnormal connection drop, # then echo data back to the client. if {[eof $sock] || [catch {gets $sock line}]} { close $sock puts "Close $echo(addr,$sock)" unset echo(addr,$sock) } else { puts $sock $line } } # # A client of the echo service. # proc Echo_Client {host port} { set s [socket $host $port] fconfigure $s -buffering line return $s } # A sample client session looks like this # set s [Echo_Client localhost 2540] # puts $s "Hello!" # gets $s line שקע (socket) השרת שרת ברשת מאזין לבקשות התחברות מלקוחות. מערכת ההפעלה יוצרת שקע חדש עבור כל התחברות של לקוח כך שהשרת יוכל לשרת מספר לקוחות בו זמנית. הפקודה socket -server קושרת את השקע עליו מאזין השרת עם פקודה אשר נקראת כאשר לקוח מתחבר אליו. אם יש לך הכרות עם עבודה עם שקעים ברמות הפשטה נמוכות יותר, Tcl מסתירה את כל הפרטים הקשורים בפקודות bind, listen ו accept. set s [socket -server EchoAccept $port] במקרה הזה, EchoAccept נקראת בכל פעם שלקוח מתחבר לשרת. על מנת שזה יעבוד, Tcl חייבת להיכנס להמתנה על לולאת אירועים כך שתיודע על בקשות התחברות. הפקודה vwait משמשת בדיוק לכך. היא מכניסה את Tcl להמתנה לאירועים עד שמשתנה מסויים משתנה. במקרה שלנו, מאחר ואין בכוונתנו לשנות את המשתנה למעשה להמתנה לנצח. מה היא לולאת אירועים לולאת האירועים הוא אמצעי מובנה ב Tcl בזמן הריצה. היא מאפשרת לך לרשום פקודות אשר יקראו מאוחר יותר כאשר אירוע מסוים יקרה. דוגמה לאירועים כוללת התחברות שקעים, מידע אשר מוכן לקלט/פלט בערוץ, אירועי טיימר. בקוד שלנו ישנן שתי פקודות הנרשמות לאירועים: socket -server המפורטת למעלה ו fileevent שתפורט בהמשך. לולאת האירועים צריכה להיות מופעלת על מנת שאירועים יתפסו ויפעילו את הפקודות הרשומות להם. כאשר עובדים עם ההרחבה Tk החלונות גורמים לכך שהלולאה מופעלת אוטומטית. בתוכניות Tcl רגילות יש להפעיל מפורשות את הלולאה. הפקודה vwait מפעילה את לולאת האירועים עד שמשתנה מסויים משתנה. התחברות לקוחות הפקודה EchoAccept נקראת כאשר לקוח מתחבר לשרת. Tclמוסיפה 3 ארגומנטים לפקודה כאשר היא נקראת בעקבות התקשרות: השקע החדש עבור ההתקשרות, כתובת ה IP של הלקוח וה Port שלו. בדוגמה שלנו כתובתו של הלקוח וה Port נשמרים במערך ובאופן כללי השרת שומר רישום על מצב כל לקוח. Line-Buffering מהשרת שם את השקע החדש למצב של Line-Buffering על מנת שכל פקודת puts תגרום לשליחת המידע ברשת. אם לא היינו מגדירים זאת Tcl היתה ממלאת חוצץ פנימי שלה ושולחת אותו ע"פ המדיניות שלה. פקודת ה fconfigure מעדכנת את הדגל המתאים. fconfigure $sock -buffering line הקלט/פלט בעקבות אירועים הפרוצדורה EchoAccept רושמת קריאה נוספת על אירוע לשם טיפול במידע שמתקבל מהלקוח שזה עתה התחבר. fileevent $sock readable [list Echo $sock] הפקודה Echo תיקרא כאשר השרת יקרא מידע משקע. עם הקישור של fileevent אנו משלימים את הפרוצדורות הדרושות לנו לטיפול בלקוח. סוף קובץ (EOF) ושגיאות הפקודה Echo בודקת האם השקע במצב של סוף קובץ. eof $sock לאחר מכן נקרא מידע מהשקע ומופעל מנגנון לתפיסת שגיאות שעוטף את הקריאה. catch {gets file line} הארגומנט הראשון ל catch הינו תסריט. Tcl תשערך את התסריט כרגיל, כך שאפשר לתחום את התסריט בסוגריים מסולסלים כרגיל. הדוגמה הזו תריץ את הפקודה gets אשר תקרא שורה מן הקלט. הפקודה הזו יכולה לגרום לשגיאה אם השקע נמצא במצב כשל מסוים. מנגנון תפיסת השגיאות יתפוס שגיאה זו. לבסוף, השרת עונה פשוט ע"י כתיבת השורה הבאה ללקוח: puts $sock $line צד הלקוח הקוד לש הלקוח הינו פשוט: set s [socket
$host $port] הפקודה הראשונה מייצרת התקשרות בעזרת שקע ה TCP אל השרת (שמפעיל את הפרוצדורה EchoAccept). הפקודה השנייה מגדירה Line-Buffering לכל פקודת puts. כבדיקה, את/ה יכול לנסות את תוכנית ה telnet של ה Unix על מנת להתחבר לשרת. רוב יישומי ה telnet דורשים מספר port כארגומנא נוסף לכתובת השרת: telnet hostname port
|
< server
< דוגמאות
server - קוד |
||||||||
|
|||||||||