שאלה כיצד לסגור את השקע בכפייה ב- TIME_WAIT?


אני מפעיל תוכנית מסוימת על לינוקס אשר לפעמים קריסות. אם אתה פותח את זה מהר אחרי זה, זה מקשיב על שקע 49201 במקום 49200 כפי שהוא עשה בפעם הראשונה. Netstat מגלה כי 49200 נמצא במצב TIME_WAIT.

האם יש תוכנית שאתה יכול לרוץ מיד לכפות כי שקע להעביר את המדינה TIME_WAIT?


109
2017-09-03 12:57




אם אתה כאן בשל "יותר מדי TIME_WAIT on, פשוט לדלג את שלוש התשובות הראשונות אשר למנוע את השאלה במקום לענות על זה. - Pacerier


תשובות:


/etc/init.d/networking restart

תן לי לפרט. Protocol Control Protocol (TCP) נועד להיות פרוטוקול שידור דו-כיווני, מסודר ואמין בין שתי נקודות קצה (תוכניות). בהקשר זה, המונח אמין פירושו שהוא ישדר מחדש את החבילות אם הוא ילך לאיבוד באמצע. TCP מבטיחה את האמינות על-ידי שליחת חבילות Acknowledgement (ACK) בחזרה עבור קבוצה אחת או טווח מנות שהתקבלו מעמיתים.

זה הולך אותו עבור אותות בקרה כגון סיום הבקשה / תגובה. RFC 793 מגדיר את זמן ההמתנה של המדינה כך:

TIME-WAIT - מייצג את ההמתנה   מספיק זמן כדי להיות בטוח       ה- TCP המרוחק קיבל את ההכרה בקשר שלו       בקשת סיום.

עיין בתרשים המדינה של TCP הבא: alt text

TCP הוא פרוטוקול תקשורת דו-כיווני, ולכן כאשר החיבור נוצר, אין הבדל בין הלקוח לשרת. כמו כן, או אחד יכול לקרוא quits, ושני עמיתים צריך להסכים על סגירה לסגור באופן מלא חיבור TCP הוקמה.

בואו נקרא הראשון לקרוא את quits כמו פעיל יותר קרוב, והשני להציץ פסיבי קרוב יותר. כאשר קרוב יותר פעיל שולח FIN, המדינה הולכת FIN-WAIT-1. ואז הוא מקבל ACK עבור ה- FIN שנשלח והמדינה הולכת FIN-WAIT-2. ברגע שהוא מקבל את ה- FIN גם מן הפסיבי קרוב יותר, קרוב יותר פעיל שולח את ACK ל- FIN והמדינה הולכת TIME-WAIT. במקרה קרוב פסיבי לא קיבל את ACK כדי השני FIN, זה יהיה לשדר מחדש את מנות ה- FIN.

RFC 793 מגדיר את TIME-OUT להיות פי שניים ממספר החיים המקסימלי, או 2MSL. מאז MSL, הזמן המרבי מנות מנותקת באינטרנט, מוגדר 2 דקות, 2MSL הוא 4 דקות. מכיוון שאין ACK ל- ACK, הפעיל קרוב יותר לא יכול לעשות דבר מלבד לחכות 4 דקות אם הוא דביק בפרוטוקול TCP / IP כראוי, רק למקרה שהשולח הפסיבי לא קיבל את ה- ACK ל- FIN שלו (באופן תיאורטי) .

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

כדי לענות על השאלה במילה, כיצד בכפייה לסגור שקע ב TIME_WAIT ?, אני עדיין מקל על התשובה המקורית שלי:

/etc/init.d/networking restart

באופן מעשי, הייתי לתכנת את זה כך שהוא מתעלם TIME-WAIT המדינה באמצעות אפשרות SO_REUSEADDR כפי WMR המוזכרים. מה בדיוק עושה SO_REUSEADDR?

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


139
2017-09-03 13:11



תשובה גדולה, אבל לא התשובה הנכונה לשאלתו. הפעלה מחדש של הרשת יעבוד, אבל אז אז היה אתחול מחדש, אז זה לא יכול להיות נכון. - Chris Huang-Leaver
@Chris Huang-Leaver, השאלה היא "האם יש תוכנית שאתה יכול להפעיל באופן מיידי כי כוח להעביר את השקע מתוך המדינה TIME_WAIT?" אם אתחול יכול להיחשב מפעיל תוכנית, אז זה גם יהיה תשובה נכונה. למה אתה חושב שזה לא יכול להיות נכון? - Eugene Yokota
WMR יש את התשובה הכי שימושי (וזה מה שאני עושה כשאני נתקל בסוג זה של בעיה). הפעלה מחדש של הרשת הוא דרסטי מדי כדי להיות פתרון, והוא יכול להימשך זמן רב יותר מאשר פשוט מחכה לתשובה. התשובה הנכונה לשאלה שלו היא 'לא', אבל אז לא אתן לך סוג שתי תשובות מכתב :-) - Chris Huang-Leaver
אה, בסדר, בפעם הבאה כמה תהליך נתקע על SIGTERM אני פשוט לרסק את המחשב שלי במקום לתקן את זה. - Longpoke


אני לא יודע אם יש לך את קוד המקור של תוכנית מסוימת שאתה מפעיל, אבל אם כך אתה יכול פשוט להגדיר SO_REUSEADDR דרך setsockopt(2) אשר מאפשר לך לאגד על כתובת מקומית זהה גם אם שקע הוא במצב TIME_WAIT (אלא אם כן זה שקע פעיל להקשיב, ראה socket(7)).

לקבלת מידע נוסף על מצב TIME_WAIT ראה שאלות נפוצות בנושא.


50
2017-09-03 13:17



אבל לא קיבלתי את השגיאה כבר מחויב. כאשר אני לבצע את התוכנית שוב זה מקשיב בהודעה (123456) גם אני יכול לראות כי המערכת מציגה TIME_WAIT עבור הנמל אבל עדיין אני יכול להתחבר. למה? - Jayapal Chandran
גם עם SO_REUSEADDR, עדיין ניתן לקבל את "כתובת כבר בשימוש" שגיאה. לפרטים, עיין בסעיף hea-www.harvard.edu/~fine/Tech/addrinuse.html. - Jingguo Yao
@WMR SO_REUSEADDR אינו "סוגר" שקע. זה רק מאפשר לך לעשות שימוש חוזר אלה שנפתחו כבר. אז השאלה היא עדיין "איך לסגור בכוח שקע ב TIME_WAIT? - Pacerier


עד כמה שאני יודע אין דרך לסגור בכוח את השקע מחוץ לכתיבת מטפל אות טוב יותר לתוכנית שלך, אבל יש קובץ / proc אשר שולט כמה זמן לוקח את הזמן. הקובץ הוא

/proc/sys/net/ipv4/tcp_tw_recycle

ואתה יכול להגדיר את הזמן הקצוב לשנייה אחת על ידי ביצוע פעולה זו:

echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle 

למרות זאת, הדף הזה מכיל אזהרה לגבי בעיות אמינות אפשריות בעת הגדרת משתנה זה.

יש גם קובץ קשור

/proc/sys/net/ipv4/tcp_tw_reuse

אשר שולט האם TIME_WAIT שקעים ניתן לעשות בה שימוש חוזר (כנראה ללא פסק זמן).

אגב, תיעוד הקרנל מזהיר אותך לא לשנות את אחד הערכים הללו ללא "ייעוץ / בקשות של מומחים טכניים". ואני לא.

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


32
2017-09-03 13:24



לחשוב על שתי הדוגמאות השני צריך להיות s / rw / tw / אני לערוך, אבל חוסר נציג מספיק.
נלקח מתוך תיעוד הקרנל: זהירות. הן tcp_tw_recycle והן tcp_tw_reuse עלולים לגרום לבעיות. אתה לא צריך לאפשר גם מבלי להבין טופולוגיה הרשת בין צומת (ים) אשר משתמשים או בשימוש על ידי הצומת שבו הפרמטר מופעל. חיבורים אשר עוברים דרך צמתים מודעים למצבים של חיבור TCP, כגון חומת אש, NAT או איזון עומסים עשויים להתחיל להטיל מסגרות בגלל ההגדרה. הבעיה תהיה גלויה כאשר יש מספר מספיק גדול של חיבורים.
הגדרת אותו 1 עובד על קשרים עתידיים, אבל מה עם אלה הנוכחי כי הם כבר נפתחו? - Pacerier


למעשה יש דרך להרוג קשר - killcx. הם טוענים שזה עובד בכל מצב של הקשר (אשר אני לא אומת). אתה צריך לדעת את הממשק שבו התקשורת קורה אם כי, נראה להניח eth0 כברירת מחדל.

עודכן: פתרון נוסף הוא חותך אשר מגיע כמה מאגרים לינוקס "distrosories.


16
2017-10-30 17:32



תודה! כלי זה עובד נהדר! הציל אותי מן הצורך להפעיל מחדש עבודה ארוכה. - Zanson


אפשרות נוספת היא להשתמש באפשרות SO_LINGER עם פסק זמן של 0. בדרך זו, כאשר אתה סוגר את השקע סגור בכוח, שולח RST במקום להיכנס להתנהגות הסגירה של FIN / ACK. הדבר ימנע ממצב TIME_WAIT וייתכן שיהיה מתאים יותר לשימושים מסוימים.


3
2018-06-10 22:33



הוא מאבד גם נתונים יוצאים שנמצאים עדיין במעבר, ועשויים לגרום לשגיאה בקצה השני. לא מומלץ. - user207421
@ EJP כשלון מוקדם הוא כמעט תמיד את השיחה הנכונה. רישות לא אמין, ואת הלחימה כי יהיה להאט את הדברים. אפליקציית התרסקות אינה יכולה להניח שכל הנתונים העלו את המידע בבטחה. - Tobu
למעשה, אני ממליץ על זה כל יום, כאשר נקודת הקצה השנייה היא באגי, מוטבע אוטובוס תעשייתי שער זה מיישמת את היישום שלה שכבת תחבורה אמין על TCP, שבו התחבורה אמר מונע את החיבור מן הסגירה אי פעם אלא אם כן הוא מקבל RST ובכך מתמלא את מגבלת החיבור באותו שער. שם. נתתי לך דוגמה מאוד ספציפית מאוד, שלמרבה הצער, היא דורשת שימוש בפריצות כאלה. - andyn
רשת Tobu אינה אמינה, אבל TCP מנסה להיות, ולהפוך את זה גרוע יותר לא עושה משהו טוב יותר, ולתת TCP לעשות את העבודה שלה אינו מהווה "לחימה" דבר. - user207421


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

אגב את היציאה שלך חיבור על גבוה למדי. אתה יכול לנסות להשתמש אחד בשימוש רק מעל טווח 10-1024. סביר שהמערכת שלך תשתמש במספר יציאה נמוך יותר כנמל זמני.


2
2017-08-21 20:28





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


0
2017-10-13 19:07