eshpilen
یک شنبه 03 بهمن 1389, 17:54 عصر
خب با یاری خدا بالاخره کوشش های بنده به ثمر رسید و تونستم الگوریتم و ارتباط P2P همراه با ترفند Port punching رو با موفقیت پیاده سازی و آزمایش کنم. این برنامه رو که فقط یک برنامهء آزمایشی برای نشون دادن الگوریتم کلی و ارتباط P2P از طریق پروتکل UDP هست در حالتهای مختلف تست کردم. آخرین و مهمترین آزمایش، ارتباط مستقیم دو PC با هم بود که هردو پشت NAT قرار داشتن؛ بطور دقیق، دو سیستم در مکانهای مختلف که به ISP های مختلفی اتصال ADSL داشتن و مودم اونها در حالت PPPoE تنظیم شده بود. البته تست های بیشتری رو برای اطمینان و فهمیدن یکسری جزییات بیشتر ممکنه در آینده انجام بدم.
برای تست این برنامه، باید به یک هاستینگ وب هم که میشه روش از PHP استفاده کرد دسترسی داشته باشید. peer ها برای اطلاع از آنلاین بودن یکدیگر و سپس اطلاع دادن آدرس عمومی خودشون به همدیگر، نیاز به این سرور واسطه دارن، اما بعد از اون درصورت موفقیت، ارتباط به حالت P2P، یعنی مستقیم و بدون استفاده از سرور واسط وارد میشه که دو طرف میتونن بصورت نامحدود تا زمانیکه ارتباط برای مدتی گسیخته نشده به این تبادل اطلاعات مستقیم ادامه بدن؛ بخاطر همین در یک برنامهء واقعی، باید در فواصل زمانی کوتاهی، مثلا هر 10 ثانیه، هر Peer حداقل یک Packet به Peer دیگر ارسال کنه تا پورت های UDP بسته نشن. البته درصورت بسته شدن ارتباط، برنامه میتونه الگوریتم برقراری ارتباط رو از نو اجرا کنه، اما اجرای مراحل این الگوریتم، باعث تاخیر قابل توجهی میشه.
طرز راه اندازی برنامه به اینصورت هست:
- ابتدا پوشه ای بنام p2p که داخل پکیج برنامه هست و دو فایل PHP داخل اون هست باید در ریشهء یک وبسایت قرار بگیره. برنامه بوسیلهء آدرسهایی مثل http://example.com/p2p/flag.php با این دو برنامهء کوچک PHP ارتباط برقرار میکنه. البته شما میتونید اول برنامه رو بصورت لوکال تست کنید و این پوشه رو بطور مثال در دایرکتوری www برنامهء EasyPHP قرار بدید.
نکتهء خیلی مهم: فایلهای PHP باید مجوز نوشتن در دایرکتوری ای رو که در اون هستن داشته باشن. بنابراین حتما اول مجوزهای لازم رو برای پوشهء p2p تعیین کنید و از اینکه برنامه های PHP میتونن در اون پوشه فایل بنویسن و بخونن مطمئن بشید؛ در غیراینصورت برنامه نمیتونه کار خودش رو انجام بده.
- مقدار متغییر intermediary رو در فایل peer1.py و peer2.py به آدرس سایت مورد نظر تنظیم کنید. مثال:
intermediary='example.com'
- مراحل بعدی دیگه خیلی ساده هست. کافیه فایل peer1.py رو روی یکی از سیستمها اجرا کنید و فایل peer2.py رو روی سیستم دیگر. اگر کمی صبر کنید و و دو سیستم اتصال اینترنت داشته باشن و مشکلی در ارتباط با وب سرور واسط نباشه، ارتباط بعد از اجرای چند مرحلهء الگوریتم برقرار میشه. این مراحل ممکنه مجموعا چند ده ثانیه تا چند دقیقه بسته به اختلال هایی که در ارتباط پیش میان زمان ببرن، بنابراین باید بقدر کافی صبر کنید. البته با تعیین مقدار sleep_time در فایلهای peer1.py و peer2.py میتونید مقدار این زمان رو کم و زیاد کنید. بطور مثال اگر مقدار این متغییر 30 باشه، هر Peer هر 30 ثانیه با سرور واسط ارتباط برقرار میکنه تا از حضور Peer دیگر مطلع بشه. همچنین موقعی که خطایی در ارتباط با سرور واسط پیش بیاد، برنامه مجدداً بعد از این زمان برای برقراری ارتباط تلاش میکنه، و غیره. بنده مقدارش رو فعلا 10 تعیین کردم که تست ها بتونن با سرعت مناسب انجام بشن، اما در یک برنامهء واقعی بسته به شرایط و کاربرد ممکنه نیاز باشه این زمان بیشتر یا کمتر باشه.
مقدار short_sleep_time رو فکر نمیکنم نیازی باشه تغییر بدید. مقدار پیشفرضش روی 2 ثانیه هست و تنها در یکجا در مراحل انتهایی تست ارتباط بکار رفته که 5 بار تکرار میشه و بنابراین 10 ثانیه بیشتر اونم بعد از موفقیت ارتباط اولیه، زمان صرف نمیکنه.
راستی دقت کنید که همهء تنظیماتی که تغییر میدید در هر دوی peer1.py و peer2.py یکسان اعمال کنید.
در انتهای برنامهء هر peer، دو خط به اینصورت وجود داره:
input('\nPress ENTER to quit...')
break
اگر بخواید برنامه بصورت مداوم اجرا بشه، مثلا موقعی که میخواید اون رو روی یک PC کار بذارید و بعد برای تست ارتباط از طریق یک PC دیگر به جای دیگری برید که سیستم اولیه دور از دسترس خواهد بود، این دو خط رو حذف یا comment out کنید تا برنامه بصورت پیوسته به کار خودش ادامه بده و مرتبا الگوریتم رو تکرار کنه تا بتونید با خیال راحت هرچندبار که میخواید از راه دور برقراری ارتباط و کارکرد صحیح الگوریتم رو تست کنید.
یادتون نره فایلهای جانبی p2p_funcs.py و stun_client.py باید در دسترس peer1.py و peer2.py باشن.
بنده سعی کردم برنامه رو تاجایی که میتونم در حالتهای مختلف و شرایطی مثل قطع شدن ارتباط اینترنت در حین اجرای الگوریتم تست و ضعفهاش رو برطرف کنم. فکر میکنم الگوریتم نهایی نسبتا قوی و منعطف باشه، اما بهرصورت فقط یک برنامهء آزمایشی برای نشون دادن الگوریتم کلی هست که درحد محدودی تست شده و هدف کامل و دقیق بودن تمام جزییات و درنظر گرفتن تمام حالات و خطاهای ممکن و نیز بهینه سازی های جزیی نبوده. ضمنا روی استایل و پارادایم کدنویسی و اینطور چیزها هم اصلا کار نکردم و از این جهت برنامه صرفا سرهم شده و احتمالا خیلی ناخوانا هست؛ چون همونطور که گفتم فقط یک برنامهء موقت برای آزمایش و نشان دادن الگوریتم و ترفند کلی بوده.
یک نکتهء دیگه اینکه، اگر دو سیستمی که برنامه ها رو روشون تست میکنید در یک LAN باشن، برای ارتباط از آدرس محلی دو سیستم، یعنی ارتباط از طریق LAN استفاده خواهد شد (این جزیی از هوشمندی لازم برای چنین برنامه هایی هست) و دیگه ارتباط از طریق اینترنت صورت نمیگیره، چون میتونه از طریق شبکهء داخلی صورت بگیره که تقریبا همیشه سرعت و امنیت بیشتر، و هزینهء کمتری داره. بنابراین برای تست واقعی و کامل برنامه در سخت ترین و پیچیده ترین شرایط واقعی، باید ارتباط LAN بین دو سیستم رو از کار بندازید. البته الگوریتم طوری هست که اگر متوجه بشه که ارتباط دو طرفه UDP از طریق LAN امکان نداره (مثلا ممکنه توسط یک فایروال بلاک بشه) اما از طریق آدرس عمومی (معمولا اینترنت) ارتباط دو طرفه ممکن هست، سعی در برقراری ارتباط از طریق آدرس عمومی میکنه. یعنی اینقدر هوشمندی رو داره و هدف این هست که ارتباط نهایی از هر راه ممکن برقرار بشه.
شاید توضیحات لازم دیگری بوده باشه که فراموش کردم بگم. بنابراین اگر به سوال یا مشکلی برخوردید حتماً مطرح کنید.
توجه: آخرین نسخهء این برنامه رو از پست شماره 5 بنده دریافت کنید. نسخه ای که ضمیمهء این پست هست نسخه ای قدیمی است.
برای تست این برنامه، باید به یک هاستینگ وب هم که میشه روش از PHP استفاده کرد دسترسی داشته باشید. peer ها برای اطلاع از آنلاین بودن یکدیگر و سپس اطلاع دادن آدرس عمومی خودشون به همدیگر، نیاز به این سرور واسطه دارن، اما بعد از اون درصورت موفقیت، ارتباط به حالت P2P، یعنی مستقیم و بدون استفاده از سرور واسط وارد میشه که دو طرف میتونن بصورت نامحدود تا زمانیکه ارتباط برای مدتی گسیخته نشده به این تبادل اطلاعات مستقیم ادامه بدن؛ بخاطر همین در یک برنامهء واقعی، باید در فواصل زمانی کوتاهی، مثلا هر 10 ثانیه، هر Peer حداقل یک Packet به Peer دیگر ارسال کنه تا پورت های UDP بسته نشن. البته درصورت بسته شدن ارتباط، برنامه میتونه الگوریتم برقراری ارتباط رو از نو اجرا کنه، اما اجرای مراحل این الگوریتم، باعث تاخیر قابل توجهی میشه.
طرز راه اندازی برنامه به اینصورت هست:
- ابتدا پوشه ای بنام p2p که داخل پکیج برنامه هست و دو فایل PHP داخل اون هست باید در ریشهء یک وبسایت قرار بگیره. برنامه بوسیلهء آدرسهایی مثل http://example.com/p2p/flag.php با این دو برنامهء کوچک PHP ارتباط برقرار میکنه. البته شما میتونید اول برنامه رو بصورت لوکال تست کنید و این پوشه رو بطور مثال در دایرکتوری www برنامهء EasyPHP قرار بدید.
نکتهء خیلی مهم: فایلهای PHP باید مجوز نوشتن در دایرکتوری ای رو که در اون هستن داشته باشن. بنابراین حتما اول مجوزهای لازم رو برای پوشهء p2p تعیین کنید و از اینکه برنامه های PHP میتونن در اون پوشه فایل بنویسن و بخونن مطمئن بشید؛ در غیراینصورت برنامه نمیتونه کار خودش رو انجام بده.
- مقدار متغییر intermediary رو در فایل peer1.py و peer2.py به آدرس سایت مورد نظر تنظیم کنید. مثال:
intermediary='example.com'
- مراحل بعدی دیگه خیلی ساده هست. کافیه فایل peer1.py رو روی یکی از سیستمها اجرا کنید و فایل peer2.py رو روی سیستم دیگر. اگر کمی صبر کنید و و دو سیستم اتصال اینترنت داشته باشن و مشکلی در ارتباط با وب سرور واسط نباشه، ارتباط بعد از اجرای چند مرحلهء الگوریتم برقرار میشه. این مراحل ممکنه مجموعا چند ده ثانیه تا چند دقیقه بسته به اختلال هایی که در ارتباط پیش میان زمان ببرن، بنابراین باید بقدر کافی صبر کنید. البته با تعیین مقدار sleep_time در فایلهای peer1.py و peer2.py میتونید مقدار این زمان رو کم و زیاد کنید. بطور مثال اگر مقدار این متغییر 30 باشه، هر Peer هر 30 ثانیه با سرور واسط ارتباط برقرار میکنه تا از حضور Peer دیگر مطلع بشه. همچنین موقعی که خطایی در ارتباط با سرور واسط پیش بیاد، برنامه مجدداً بعد از این زمان برای برقراری ارتباط تلاش میکنه، و غیره. بنده مقدارش رو فعلا 10 تعیین کردم که تست ها بتونن با سرعت مناسب انجام بشن، اما در یک برنامهء واقعی بسته به شرایط و کاربرد ممکنه نیاز باشه این زمان بیشتر یا کمتر باشه.
مقدار short_sleep_time رو فکر نمیکنم نیازی باشه تغییر بدید. مقدار پیشفرضش روی 2 ثانیه هست و تنها در یکجا در مراحل انتهایی تست ارتباط بکار رفته که 5 بار تکرار میشه و بنابراین 10 ثانیه بیشتر اونم بعد از موفقیت ارتباط اولیه، زمان صرف نمیکنه.
راستی دقت کنید که همهء تنظیماتی که تغییر میدید در هر دوی peer1.py و peer2.py یکسان اعمال کنید.
در انتهای برنامهء هر peer، دو خط به اینصورت وجود داره:
input('\nPress ENTER to quit...')
break
اگر بخواید برنامه بصورت مداوم اجرا بشه، مثلا موقعی که میخواید اون رو روی یک PC کار بذارید و بعد برای تست ارتباط از طریق یک PC دیگر به جای دیگری برید که سیستم اولیه دور از دسترس خواهد بود، این دو خط رو حذف یا comment out کنید تا برنامه بصورت پیوسته به کار خودش ادامه بده و مرتبا الگوریتم رو تکرار کنه تا بتونید با خیال راحت هرچندبار که میخواید از راه دور برقراری ارتباط و کارکرد صحیح الگوریتم رو تست کنید.
یادتون نره فایلهای جانبی p2p_funcs.py و stun_client.py باید در دسترس peer1.py و peer2.py باشن.
بنده سعی کردم برنامه رو تاجایی که میتونم در حالتهای مختلف و شرایطی مثل قطع شدن ارتباط اینترنت در حین اجرای الگوریتم تست و ضعفهاش رو برطرف کنم. فکر میکنم الگوریتم نهایی نسبتا قوی و منعطف باشه، اما بهرصورت فقط یک برنامهء آزمایشی برای نشون دادن الگوریتم کلی هست که درحد محدودی تست شده و هدف کامل و دقیق بودن تمام جزییات و درنظر گرفتن تمام حالات و خطاهای ممکن و نیز بهینه سازی های جزیی نبوده. ضمنا روی استایل و پارادایم کدنویسی و اینطور چیزها هم اصلا کار نکردم و از این جهت برنامه صرفا سرهم شده و احتمالا خیلی ناخوانا هست؛ چون همونطور که گفتم فقط یک برنامهء موقت برای آزمایش و نشان دادن الگوریتم و ترفند کلی بوده.
یک نکتهء دیگه اینکه، اگر دو سیستمی که برنامه ها رو روشون تست میکنید در یک LAN باشن، برای ارتباط از آدرس محلی دو سیستم، یعنی ارتباط از طریق LAN استفاده خواهد شد (این جزیی از هوشمندی لازم برای چنین برنامه هایی هست) و دیگه ارتباط از طریق اینترنت صورت نمیگیره، چون میتونه از طریق شبکهء داخلی صورت بگیره که تقریبا همیشه سرعت و امنیت بیشتر، و هزینهء کمتری داره. بنابراین برای تست واقعی و کامل برنامه در سخت ترین و پیچیده ترین شرایط واقعی، باید ارتباط LAN بین دو سیستم رو از کار بندازید. البته الگوریتم طوری هست که اگر متوجه بشه که ارتباط دو طرفه UDP از طریق LAN امکان نداره (مثلا ممکنه توسط یک فایروال بلاک بشه) اما از طریق آدرس عمومی (معمولا اینترنت) ارتباط دو طرفه ممکن هست، سعی در برقراری ارتباط از طریق آدرس عمومی میکنه. یعنی اینقدر هوشمندی رو داره و هدف این هست که ارتباط نهایی از هر راه ممکن برقرار بشه.
شاید توضیحات لازم دیگری بوده باشه که فراموش کردم بگم. بنابراین اگر به سوال یا مشکلی برخوردید حتماً مطرح کنید.
توجه: آخرین نسخهء این برنامه رو از پست شماره 5 بنده دریافت کنید. نسخه ای که ضمیمهء این پست هست نسخه ای قدیمی است.