עבור לתוכן

הגדרת TcpClient בסביבת .Net framework לתקשורת בצורה הכי מהירה

Featured Replies

פורסם

שלום לכולם,

אני יושב על פרוייקט גמר שנכתב ב-VB .net

בפרוייקט יש לנו כ-5 מחשבים שמתקשרים באמצעות הראוטר,

בניתי את השרת ואת הקליינטים השונים בהתבססות על מחלקת ה-TcpClient

מפני שאני צריך שהתקשורת תיהיה כמה שיותר מהירה אני מעוניין

לדעת מהן ההגדרות הכי טובות שאצטרך להגדיר בכדי שהמידע יעבור בין

המחשבים בצורה המהירה והטובה ביותר. ההגדרות שביינתים יצא לי לשחק

איתן הן SendBufferSize , RecieveBufferSize ו-NoDelay.

מפני שהייתי צריך לנתח את המידע שאני מקבל ולעבור בייט בייט, ככול שהSendBufferSize

וה-RecieveBufferSize גדולים יותר יש עליי לסרוק יותר בייטים, וייתכן שרוב הבייטים

שישלחו יהיו בעלי ערך של אפס בגלל שהמידע שאני שולח הוא מידע קטן (כמה בייטים סה"כ)

אצטרך לעבור גם על הבייטים שהם אפסים (עודף של מידע לא נחוץ), מה שעלול לגרום למהירות תגובה איטית יותר

מה שאני בדיוק לא צריך - לבסוף החלטתי להישתמש בהגדרות הבאות:

SendBufferSize = 50

RecieveBufferSize = 50

NoDelay =True

ובחזרה לשאלה שלי, האם ישנן הגדרות נוספות/ הגדרות טובות יותר?

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

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

פורסם

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

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

למשל, לפני שאתה שולח 8 בתים, תשלח לנמען קודם כל את מספר הבתים שהוא עומד לקבל, ואז תעדכן בהתאם את גודל ה BUFFERS של השולח ושל המקבל בהתאם לגודל החבילה.

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

ננסה להמחיש את זה יותר טוב:

אתה רוצה לשלוח 30 בתים ממחשב X למחשב Y.

טיפול במחשב X:

מה שכדאי לעשות לפני שאתה שולח את ה 30 בתים, זה להגדיר במחשב X ששולח, את גודל ה BUFFER שנשלח, לבית אחד.

(תדאג גם שגודל ה BUFFER של מחשב Y שמקבל יהיה בית אחד, כברירת מחדל).

עכשיו, תשלח בית בודד ממחשב X למחשב Y, שמציין את כמות הבתים שעומדת להישלח, כלומר, תשלח בית/תו שערכו המספרי הוא 30.

ומיד לאחר מכן, תגדיר מחדש במחשב X ששולח את גודל ה BUFFER לשליחה, שיהיה 30, ותשלח את הבתים שרצית לשלוח בהתחלה.

ברגע שסיימת לשלוח את 30 הבתים, תגדיר מחדש את גודל ה BUFFER לשליחה שיהיה בגודל בית אחד, כדי לחזור למצב ההתחלתי שבו היינו.

עכשיו הטיפול במחשב Y שמקבל את הבתים:

מחשב Y מקבל את הבית הבודד הזה, מפענח אותו (קרא 30), ואז מתכונן לקבל את שאר הבתים, כלומר, יגדיר לעצמו את גודל ה BUFFER שמתקבל, ל 30 בתים, ואז אחרי שאתה מקבל אותם, כמו במחשב X, גם פה תגדיר מחדש את גודל ה BUFFER שמתקבל לבית אחד כדי להיות מוכן לקבלת חבילות נוספות בעתיד.



עכשיו כשאני חושב על זה, גודל ה RECIEVE BUFFER לא באמת משנה, תגדיר אותו אפילו שיהיה 50 בתים.

אבל הרעיון הוא אותו רעיון רק יותר פשוט.

רוצה לשלוח 30 בתים? דחוף לפניהם בית נוסף, שמציין את גודל המידע שיש לשלוח ולקרוא בצד השני, כלומר, הבית הזה שאתה מוסיף יכיל את הערך 30. סה"כ יש לך עכשיו 31 בתים לשלוח, אז תגדיר את ה SEND BUFFER שיהיה 31, ותשלח את הבתים האלו במכה.

עכשיו, כשהמחשב השני מקבל את החבילה, לפני שאתה קורא את כל ה BUFFER שהגיע, תקרא רק את הבית הראשון, ערכו יהיה 30, ועכשיו אתה תדע לקרוא רק את 30 הבתים הבאים שיש ב RECIEVE BUFFER.

ככה תדאג שה SEND BUFFER יהיה דינאמי בהתאם לגודל הבתים שאתה רוצה לשלוח כל פעם.

אני לא רואה פתרון אחר, עזוב את מה שכתבתי לפני זה, סתם מיותר כל העסק של ה RECIEVE BUFFER כי הגודל שלו לא אמור להשפיע על מהירות השליחה. אבל אם מתישהו תרצה לשלוח חבילות הרבה יותר גדולות, כמו קבצים, אז תדאג שה RECIEVED BUFFER גם יהיה דינאמי כמו שהצעתי לפני זה במקום לקבוע לו גודל מקסימלי)

מוזר שכלכך הרבה אנשים קראו פה את ההודעה ולא בא מישהו נוסף עם רעיון....

בכל מקרה אני לא רואה פתרון אחר.

בהצלחה ותעדכן!

פורסם
  • מחבר

שלום ותודה רבה על התגובה, אני מעריך את זה.

הרעיון שלך נשמע טוב ואני מאמין שיעבוד אבל בגלל שהתקשורת שלי

היא תקשורת עם כמה מחשבים המחוברים לאותו השרת אני צריך גם לזהות

ממי נשלח והיתקבל המידע.

התקשורת שבניתי לא ממש פשוטה מהבחינה הזאת, בגלל העניין של התקשורת עם חמישה מחשבים שונים

אז צורת המחשבה שחשבתי עלייה היא הדבר הבא:

כול המחשבים מתחברים לשרת אחד, כול מחשב שמתחבר חייב להיות בעל מזהה (ID)

בכדי שנוכל לשלוח מידע בין מחשב אחד לאחר (להעביר את המידע ממחשב אחד לאחר שהוא לא השרת)

המשתמש שולח את ההודעה עם המזהה של המשתמש שהוא רוצה שיקבל את ההודעה,

השרת מקבל את ההודעה מנתח את ההודעה ומוצא את המזהה של המשתמש שצריך לקבל את ההודעה,

לאחר שמצא למי הוא צריך להעביר את ההודעה, הוא שולח את ההודעה ובהודעה רשום את המזהה של מי ששלח,

מה שעשיתי בעיקרון זה חילקתי את הבייטים ככה:

כול הודעה מתחילה עם בייט בעל ערך של 33, (שזה יוצא התו "!" מאסקי)

וככה בעצם אני שולח את ההודעה:

! שם השולח !מספר הבייטים שמכילה ההודעה! ההודעה

כאשר האלגוריתם שלי מחפש את הבייט שמתחיל את ההודעה (33) הוא מתחיל לחפש את המזהה

של המשתמש ששלח, המזהה של המשתמש חייב להיות בלי התו 33, ככה שהמזהה של המשתמש נמצא

בין 2 התווים "!" (או הערך שלהם באסקי 33) לאחר שהמזהה נמצא, האלגוריתם מוצא את מספר הבייטים

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

ההודעה נמסרת לשרת שהוא יטפל בה (בגלל שההודעה נועדה אליו)

בעיקרון, השיטה אכן עובדת והיא עשתה לי בעיות כאשר שמתי RecieveBufferSize של 50,

לאחר ששינתי אותו ל-400 לא היו שום בעיות והכול עובד באופן מצויין (בגלל שהמידע שנשלח כניראה

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

איטי אני יודע שפרוטוקול ה-TCP לא אמור להיות למשחקים ולא אמור להיות מהיר,

אך בגלל שהתקשורת מספיק מסובכת התבססתי עליו בעיקרון המידע נשלח במהירות

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

דרך הראוטר באותו החדר ככה שאולי כן פרוטוקול ה-TCP מתאים לפה.

בעיקרון אני צריך מהירות בגלל שבפרוייקט גמר הרובוט שלנו אמור "לירות" בנשקים

שיש דיליי שונה בין ירייה לירייה בין כול נשק ונשק, והנשק הכי מהיר הוא ה-SMG

בעיקרון כול שאר הנשקים עובדים מצויין לדעתי - כניראה שאולי אני מבקש

יותר מידי ואולי אני יעלה פשוט את הדיליי בין ירייה לירייה.

ההגדרות שבינתיים עבדו הכי טוב הן:

SendBufferSize=50

ReceiveBufferSize=50

NoDelay=True

פורסם

אני כבר לא מבין כלכך מה אתה רוצה.

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

כשאמרת ש"השיטה אכן עובדת" התכוונת לשיטה שלי או לשיטה שלך?

אני לא מבין למה אתה לא יכול לעשות את זה.

מה זה משנה כמה מחשבים מעורבים?

כל מחשב ששולח הודעה לשרת, תדאג להוסיף בית שמציין את גודל ההודעה, כדי שהשרת ידע כמה בתים לקרוא, במקום שהוא יקרא את כל גודל ה BUFFER שהקצאת לו.

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

מה שאתה מנסה ליישם מאוד פשוט, אם היית כותב את זה ב C# הייתי עוזר לך עם הקוד. אם אתה רוצה לא אכפת לי לנסות, כל ת'כלס רוב העבודה היא גם ככה בסביבת NET.

אם TCP לא מספיק מהיר בשבילך ברשת פנימית, תשקול לממש באמצעות UDP (אין לי מושג איך).

פורסם
  • מחבר

שלום שוב ותודה רבה, יש לי את הקוד כבר כתוב (ב-VB .net)

השיטה שאני עובד איתה עכשיו (כמו שתיארתי למעלה) עובדת אך לא בצורה מהירה וכאשר

ה-ReceiveBufferSize היה בערך של 50 היה איבוד מידע (או במילים אחרות האלוגריתם לא עבד) אבל לאחר

ששינתי אותו ל-400 הכול עובד.

אני אבדוק את התיקשורת שלנו שוב ואחליט, ייתכן ואם לאחר כמה שינויים

שעשיתי עדיין התיקשורת לא תיהיה מספיק מהירה אני אנסה את השיטה שהצעת.

בנוסף אשמח לדעת אם ישנם עוד הגדרות במחלקה שאפשר להיתעסק איתם שאולי יכולים

לעזור עוד. ושוב תודה רבה, אני מעריך את זה!

ארכיון

דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.

דיונים חדשים