ورود

View Full Version : سوال: تشخيص خروج نامتعارف - (سوکت پروگرمینگ)



negative60
دوشنبه 22 اردیبهشت 1393, 03:06 صبح
خيلی وقته تو برنامه نويسی سوکت با API در c++ و يا در کلاس های کار با سوکت در .net با يک مشکل بزرگ روبرو شدم زمانی که اتصال tcp يک کلاينت با سرور به صورت نامتعارف قطع بشه (قطع ارتباط شبکه، قطع اينترنت، خاموش شدن ناگهانی کامپيوتر کلاينت و ..) سرور هيچ باز خوردی مبنی بر اينکه کلاينت ديسکانکت شده دريافت نميکنه به صورتی که انگار کلاينت آنلاين هست تا زمانی که يک پکت به کلاينت ارسال کنيم بعد از حدود 1 ، 2 دقيقه سرور پاسخ ديسکانيت شدن کاربر رو دريافت ميکنه.

سؤال من اينه که چطور ميشه اين مشکل رو حل کرد به صورتی که نياز نباشه برای تشخيص ديسکانت شدن کاربر پکتی به کلاينت ارسال کنيم چون خود همين فرستادن پکت تو تعداد بالا کلاينت حتی تو بازه های زمانی مختلف به هر حال منابعی مصرف ميکنه.


و همچنين سرور های بزرگ و معروف با اين مشکل چطور برخورد ميکنند؟

joker
دوشنبه 22 اردیبهشت 1393, 17:01 عصر
توی سوکت پروگرامینگ خالص درستش اینه که کلاینت موقع قطع شدن یک پکت close بفرسته ولی خب وقتی ارتباط غیرعادی قطع میشه این پکت به سرور ارسال نمیشه و خود سیستم عامل پس از مدتی این قضیه را هندل میکنه و اون پورت را اشغال شده را آزاد میکنه ، نگرانش نباش خلاصه... اما اگه این آنلاین بودن و این فاصله 2 دقیقه ای ( عدد معمول زمان در این مورد) برای سیستمت خیلی مهمه تنها راه هندشیک کردن لحظه به لحظه هست که در هر حال بار زیادی به سیستمت اعمال میکنه. نمیتونی دقت را فدای کمیت بکنی ( بازم بستگی به ساختار نرم افزارت داره)

negative60
دوشنبه 22 اردیبهشت 1393, 17:47 عصر
بنده به شخصه بیش از چند بار تا حالا در این رابطه توضیح دادم.
در دلفی رو عرض میکنم:
در مجموعه Indy:
در این مجموعه بعد از اینکه کاربری به TCPServer متصل شد در قسمت Connected دستور

(AContext.Binding.IP);
میتونید کاربری که متصل شده رو ببینید.
به محض دیسکانکت شدن هم در رویداد DisConnected می تونید از دیسکانکت شدنش با خبر بشید.

مشکلی با ديدن کاربرای آنلاين ندارم عرض کردم ديسکانکت شدن نا معمول و غير عادی



توی سوکت پروگرامینگ خالص درستش اینه که کلاینت موقع قطع شدن یک پکت close بفرسته ولی خب وقتی ارتباط غیرعادی قطع میشه این پکت به سرور ارسال نمیشه و خود سیستم عامل پس از مدتی این قضیه را هندل میکنه و اون پورت را اشغال شده را آزاد میکنه ، نگرانش نباش خلاصه... اما اگه این آنلاین بودن و این فاصله 2 دقیقه ای ( عدد معمول زمان در این مورد) برای سیستمت خیلی مهمه تنها راه هندشیک کردن لحظه به لحظه هست که در هر حال بار زیادی به سیستمت اعمال میکنه. نمیتونی دقت را فدای کمیت بکنی ( بازم بستگی به ساختار نرم افزارت داره)


هندشیک کردن منظورتون همون فرستادن پکت هست ؟
زمانی که کاربر به صورت غير عادی ديسکانکت ميشه در سرور بعد از چند ساعت هم هيچ پکتی دريافت نميشه اگر 2 ، 3 دقيقه باشه که هيچ مشکلی نيست! مشکل همينجاست تو برنامه کاربر منابعی گرفته و تا زمانی که خارج نشه اشغال خواهد موند و همچنين کاربرای ديگه اين يوزر رو آنلاين ميبينند

تنها راهی که به ذهنم رسيد فرستادن پکت 1 بايتی در فواصل 1 دقيقه اي به تمام کاربرهاست در اين صورت اگر کاربری به صورت غير معمول ديسکانت شده باشه بعد از گذشت حدود 2 دقيقه سوکت مربوط به کلاينت پکت close رو دريافت ميکنه

negative60
دوشنبه 22 اردیبهشت 1393, 19:39 عصر
دوست من پروژه با c++ هست نه دلفی البته اين مشکل رو تو سوکت برنامه های .net هم داشتم
به هر حال تو کامپوننت های دلفی هم از API ويندوز استفاده ميشه اگر اينطور که شما ميگيد باشه فکر کنم راه حلی به جز فرستادن پکت هم بايد وجود داشته باشه

negative60
دوشنبه 22 اردیبهشت 1393, 23:51 عصر
خوشبختانه راه حل رو پيدا کردم به وسيله تابع ای پی آی WSAIoctl و کد کنترل SIO_KEEPALIVE_VALS ميشه اين مشکل رو برطرف کرد که البته تو زبان های ديگه هم ميشه ازش استفاده کرد.
نمونه مثال طريقه استفاده (http://www.winsocketdotnetworkprogramming.com/winsock2programming/winsock2advancedsocketoptionioctl7f.html) , فقط يک نکته من زمان keepalivetime رو به 60000 (60 ثانيه) تغيير دادم تا تتيجه دلخاه رو گرفتم.




Alternatively, you can enable SO_KEEPALIVE, but the keepalive interval of this option is usually OS-dependent and I would not recommend using it.
يکی هم توصيه کرده از اين روش استفاده نکنيد چون به سيستم عامل وابسته هست! منظورش رو نميفهمم چه اشکالی داره وابسته باشه؟