تسهيل در ساخت برنامه‌‌های كاربردی P2P، قسمت 1

نويسنده: Sayed Ibrahim Hashimi
Java world
مترجم: امين ايزدپناه

 

توسعه برنامه‌های كاربردی P2P را با استفاده از Jxta و انقياد (binding) جاوای آن آغاز نماييد.

 

خلاصه

با وجود محبوبيت روزافزون برنامه‌هاي كاربردي نظير به نظير (P2P)، چنان كه برنامه‌هايي مانند Kazaa و پيام‌رسان فوري AOL اين امر را به اثبات رسانده‌اند، نياز به يك شالوده قابل اطمينان براي ساخته شدن برنامه‌هاي كاربردي جديد بر پايه آن اجتناب‌ناپذير است. Jxta و انقياد جاواي آن فرايند ايجاد اين شالوده را آغاز نمود. Jxta مجموعه‌اي از پروتكل‌هاي مستقل از سيستم‌عامل، مستقل از زبان، و مستقل از شبكه است كه در ابتدا توسط Sun Microsystems توسعه داده شد و سپس به جامعه open source عرضه گرديد. با عرضه آن همچنين يك پياده‌سازي اوليه در جاوا ارائه شد. Jxta به برنامه‌نويسان برنامه‌هاي كاربردي امكان توسعه سريع برنامه‌هاي P2P را مي‌دهد. در اين مقاله، بخش نخست از سري دو قسمتي، نويسنده نگاهي دارد به عملكردهاي معمول يك برنامه كاربردي Jxta و آنها را به صورت مفصل شرح مي‌دهد، ضمن آن كه يك سري كد براي مطالعه خوانندگان فراهم مي‌آورد. در قسمت 2، نويسنده به بررسي برخي از تكنيك‌هاي پيشرفته‌تر Jxta خواهد پرداخت و براي تشريح كامل آنها اقدام به ارائه يك برنامه كاربردي خواهد نمود.

 گفته شده است Kazaa، برنامه اشتراك فايل نظير به نظير (P2P)، بيش از هر برنامه ديگري باعث ترافيك شبكه مي‌گردد. وب‌سايت Kazaa اعلام كرده كه بيش از 385 ميليون دانلود از آن صورت گرفته است! براي بررسي اين موضوع، من ليست بيشترين دانلودهاي Download.com را مشاهده نمودم، ليستي كه Ad Aware را با 117 ميليون دانلود به عنوان محبوب‌ترين دانلود معرفي مي‌نمايد. در ميان 25 دانلود نخست Download.com، من 11 برنامه P2P را مشاهده كردم. تنها با همين مشاهدات، مي‌توان دريافت كه برنامه‌هاي P2P آشكارا در حال دستيابي به محبوبيت رو به رشد هستند. اما اشتراك فايل تنها نوع از برنامه‌هاي P2P نيست. اغلب عملكردهاي يك برنامه نوعي پيا‌رساني فوري، P2P است. به عنوان مثال‌هاي ديگر مي‌توان از پايگاه‌هاي داده توزيع شده و انجمن‌ها نام برد. و اين ليست همچنان به رشد خود ادامه مي‌دهد.

براي ايجاد برنامه‌هاي P2P مانند اين، شما بايد راهكاري براي يافتن ساير مخاطبان (peer ها) و تعامل با آنها داشته باشيد. اغلب مشكلات موجود بر سر راه ايجاد برنامه‌هاي P2P مربوط به نگهداري شبكه مخاطبان، قالب‌بندي و انتقال پيام‌ها، يافتن ساير مخاطبان، و مسائل مشابه ديگر مي‌باشد. پروژه Jxta و انقياد جاواي آن اين جنبه‌هاي برنامه شما را اداره مي‌نمايد. با استفاده از Jxta، شما مي‌توانيد بر روي برنامه خود تمركز نماييد، نه بر مسائل كلي P2P.

Jxta عبارت اختصاري لغت juxtapose است، كه به معني پهلو به پهلو مي‌باشد. راهنماي برنامه‌نويسان Jxta آن را به عنوان "يك پلاتفرم محاسبه‌گري باز كه براي محاسبه‌گري P2P طراحي شده است" تعريف مي‌نمايد. آن نه خاص يك پلاتفرم است نه خاص يك زبان برنامه‌نويسي. آن در Sun Microsystems شكل گرفته و براي نگهداري و توسعه به جامعه open source ارائه شده است. به همراه عرضه آن، يك پياده‌سازي اوليه جاوا انتشار يافت. من در اين مقاله بر روي آن پياده‌سازي تمركز مي‌كنم به نحوي كه شيوه استفاده از Jxta در يك محيط جاوا را مورد بحث قرار مي‌دهم. من همچنين شش عملكرد معمول برنامه‌هاي Jxta پياده‌سازي شده در جاوا را مطرح مي‌كنم و ابزارهاي مورد نياز شما براي نوشتن برنامه‌هاي P2P خودتان را معرفي مي‌نمايم. پس از مطالعه‌ي اين مقاله، من اميدوارم  شما دريابيد كه ايجاد برنامه‌هاي كاربردي P2P مي‌تواند تا چه حد ساده و مهيج باشد. برنامه‌هاي P2P نه تنها از لحاظ محبوبيت به رشد خود ادامه خواهند داد، بلكه از جنبه‌ي تنوع نيز اين گونه خواهد بود، و توسعه‌دهندگان فردا بايد براي به روز ماندن، آموختن اين تكنولوژي‌ها را امروز آغاز نمايند.

 

جاوا و Jxta

نخستين گام براي استفاده از Jxta، دانلود كردن آن از آدرس http://download.jxta.org است. همچنان كه اغلب خوانندگان تاييد مي‌نمايند، گاهي اوقات تهيه و تنظيم پروژه‌هاي open source براي استفاده مي‌تواند دشوار باشد. Jxta مثالي از يك پروژه عظيم open source است كه همچنين دانلود و استفاده از آن بسيار آسان مي‌باشد. اگر شما با مشكلي مواجه گرديديد و نيازمند اطلاعات بيشتري در مورد دانلود و استفاده از Jxta بوديد، به راهنماي برنامه‌نويس Jxta در آدرس http://www.jxta.org/docs/JxtaProgGuide_v2.3.pdf مراجعه كنيد.

هنگامي كه شما براي نخستين بار اقدام به اجراي يك برنامه كاربردي داراي قابليت Jxta از يك دايركتوري جديد مي‌نماييد، تنظيم‌گر GUI در اختيار شما قرار داده مي‌شود. در قسمت 2، من به شما نشان خواهم داد كه چگونه مي‌توانيم از بسته Jxta ext براي پيكربندي يك مخاطب (peer) استفاده كنيم تا ديگر نيازي به تنظيم‌گر UI نباشد.

يك مخاطب دقيقا چيست؟ بر اساس گفته Daniel Brookshire (يك committer معروف Jxta و به قول بعضي‌ها "قهرمان")، آن يك "نقطه ارتباط مجازي" است، در حالي كه مخاطبان مختلف مي‌توانند بر روي يك ابزار قرار داشته باشند. ابزار به يك PC محدود نمي‌شود؛ آن مي‌تواند يك تلفن موبايل، يك سرور، يا حتي آيتمي به سادگي يك سنسور باشد. يك سري مخاطبان خاص نيز وجود دارد، كه دو تا از آنها كه لازم است از سوي ما شناخته شوند rendezvous و relay مي‌باشند. يك مخاطب rendezvous به مخاطبان امكان برقراري ارتباط با خارج حوزه زيرشبكه محلي را مي‌دهد، و يك مخاطب relay براي انتقال اطلاعات از ميان فايروال‌ها مورد استفاده قرار مي‌گيرد.

بياييد با بررسي شش عملكرد معمول برنامه‌هاي Jxta كار خود را آغاز كنيم، چنان كه در "هزينه‌هاي استفاده از Jxta" (انجمن كامپيوتر IEEE، سپتامبر 2003) موجود در آدرس http://csdl.computer.org/comp/proceedings/p2p/2003/2023/00/20230160abs.htm تعريف گرديده است. آنها در ادامه به ترتيبي كه معمولا رخ مي‌دهند ليست شده‌اند:

  1. آغاز نمودن Jxta: آغاز نمودن Jxta به شكل دلپذيري ساده است، به سادگي چند خط كد.
  2. ملحق شدن به يك گروه مخاطب: يك گروه مخاطب، مجموعه‌اي از مخاطبان داراي يك مجموعه‌ي مشترك از علايق است كه در كنار يكديگر يك گروه را تشكيل داده‌اند. در اين مقاله، من موضوع ملحق شدن به گروه‌هاي مخاطب موجود و ايجاد گروه‌هاي مخاطب جديد را تشريح مي‌كنم.
  3. منتشر ساختن آگهي‌ها: آگهي‌ها همه چيز Jxta هستند. Jxta از آگهي براي يافتن مخاطبان، گروه‌هاي مخاطب، و ساير منابع به يك شيوه مستقل از پلاتفرم استفاده مي‌نمايد. من در ادامه اين مقاله خواندن، ايجاد، و ارسال آگهي‌هاي جديد را مورد بحث قرار مي‌دهم.
  4. گشودن يك لوله جديد: يك لوله ساز و كاري است كه مخاطبان از آن براي برقراري ارتباط با يكديگر استفاده مي‌كنند. لوله‌ها "كانال‌هاي ارتباط مجازي" هستند – مجازي به اين معني كه كاربران استفاده كننده از يك لوله، از آدرس واقعي مخاطب ديگر آگاهي ندارند. من موضوع استفاده از لوله‌ها به منظور ارسال پيام را در اين مقاله مورد بررسي قرار خواهم داد.
  5. شناسايي منابع مخاطب ديگر: قبل از آن كه شما بتوانيد با مخاطبان ديگر ارتباط برقرار نماييد، شما بايستي يك سري چيزها را بيابيد، كه من به بحث در مورد آنها نيز خواهم پرداخت.
  6. گشودن يك لوله‌ي خروجي: لوله‌هاي خروجي براي ارسال پيام‌ها به ساير مخاطبان به كار برده مي‌شوند. دو رده از لوله‌هاي خروجي وجود دارد: نقطه به نقطه، يا يك به يك، و انتشاري، يا يك به چند.

 

حالا كه متوجه شديد اين مقاله شما را به كجا رهنمون خواهد شد، بياييد سفرمان را آغاز نماييم.

 

گروه‌هاي مخاطب

گروه‌هاي مخاطب، مجموعه‌اي از مخاطباني است كه داراي علايق مشترك هستند. گروه‌هاي مخاطب، همانند مخاطبان، مي‌توانند خدماتي را فراهم آورند، و در عين حال يك سرويس گروه مخاطب لزوما به يك مخاطب خاص كه درخواست‌ها را براي آن گروه انجام مي‌دهد وابسته نيست. مادامي كه يك مخاطب واحد در گروه سرويس را فراهم مي‌آورد، سرويس در دسترس است. هر مخاطب عضوي از گروه مخاطب جهاني (world peer group) است و همچنين، به طور كل، گروه مخاطب نت (net peer group)، و مي‌تواند با اراده خود به گروه‌هاي ديگر ملحق گردد يا آنها را ترك نمايد. چه انگيزه‌اي براي ايجاد گرو‌ه‌هاي مخاطب وجود دارد؟ در ادامه چند دليل را براي اين امر مشاهده مي‌كنيد:

·          نگهداري ناحيه امن: اگر شما داراي يك گروه مخاطب امن باشيد، اطلاعات حياتي مخاطبان موجود در گروه افشا نخواهد شد.

·          فراهم ساختن خدمات مشترك: معمولا، بسياري از مخاطبان خواهان استفاده از/فراهم ساختن خدمات يكسان هستند، بنابراين انجام اين كار در گروه مناسب و مطلوب به نظر مي‌رسد. براي مثال، شما مي‌توانيد يك سرويس چاپگر يا پايگاه‌داده‌ي توزيع‌شده را براي تمامي مخاطبان حاضر در گروه فراهم آوريد.

·          محدود ساختن حوزه ID: نام لوله‌ها با گروهي كه در آن ايجاد شده‌اند مطابقت دارد. اگر دو لوله داراي يك نام باشند، اما در يك گروه ساخته نشده باشند، در اين صورت هيچ مشكلي براي كار با آنها وجود ندارد.

 اجازه دهيد ببينيم چگونه مي‌توانيم كار ايجاد و ملحق شدن به يك گروه مخاطب را انجام دهيم. روش‌هاي فراهم شده از سوي رابط PeerGroup در ادامه ليست شده‌اند. در قسمت 2، من به شرح برخي روش‌هاي ساده‌تر براي ايجاد و ملحق شدن به گروه‌هاي مخاطب خواهم پرداخت.

·          newGroup (Advertisement pgAdv)i: معمولا براي نمونه‌سازي (instantiate) يك گروه موجود با آگهي گروه يافت شده مورد استفاده قرار مي‌گيرد.

·          newGroup (PeerGroupID gid, Advertisement impl, String name, String description): معمولا براي ساختن گروه‌هاي مخاطب جديد به كار برده مي‌شود.

·          newGroup (PeerGroupID gid)i: براي نمونه‌سازي (instantiate) يك گروه مخاطب موجود و منتشر شده فقط با ID گروه مخاطب (gid) استفاده مي‌شود.

 

ايجاد گروه‌هاي مخاطب

ايجاد يك گروه مخاطب بنياني كار نسبتا ساده‌اي است. بياييد به كدي كه در ادامه آمده نگاهي بياندازيم:

 

try
{
    //We will create a new group based on the netPeerGroup so let's copy its
    //impl advertisement and modify it.
    ModuleImplAdvertisement implAdv =
      netPeerGroup.getAllPurposePeerGroupImplAdvertisement();

    myPeerGroup = netPeerGroup.newGroup(
            null,               //Create a new group id for this group.
            implAdv,            //Use the above advertisement.
            "Group name",       //This is the name of the group.
            "Group description" //This is the description of the group.
            );

    System.out.println("---Peer group created successfully, id: " +
      myPeerGroup.getPeerGroupAdvertisement().getID() );

    //Now that the group is created, it is automatically published and stored locally,
    //but we need to publish it remotely so other peers can discover it.
    discoveryService.remotePublish( myPeerGroup.getPeerGroupAdvertisement() );
    System.out.println("---Published peer group advertisement remotely");
}

catch (Exception e)
{
    System.out.println("An error occurred");
    e.printStackTrace();
}

 

فراخواني newGroup() گروه را ايجاد و به كش محلي انتشار مي‌دهد. به احتمال قريب به يقين، شما خواهان انتشار اين آگهي (هنگامي كه آن را ايجاد مي‌نماييد) به ساير مخاطبان خواهيد بود، كه شما مي‌توانيد اين كار را با فراخواني remotePublish() انجام دهيد. اين متد آگهي گروه مخاطب را به ساير مخاطبان خواهد رساند. اگر شما بايد اطمينان يابيد كه آگهي را به مخاطبان حاضر در زيرشبكه ديگر فرستاده‌ايد، بايد اطمينان حاصل كنيد كه به يك مخاطب rendezvous متصل هستيد. براي انجام اين كار، از كدي كه در ادامه آمده است استفاده نماييد، با اين فرض كه مخاطب rendezvous شما به درستي مشغول كار كردن است و به شكلي صحيح تنظيم گرديده است:

 

private void connectToRdv(PeerGroup peerGroup)
{
    if( rdv == null)
    {
        //Get the rdv service
        rdv = peerGroup.getRendezVousService();
    }

    //Make sure that we are connected before proceeding
    while( !rdv.isConnectedToRendezVous() )
    {
        try
        {
            Thread.sleep(5000);
        }
        catch (InterruptedException e1)
        {
            System.out.println("rdv connect interrupted");
            e1.printStackTrace();
        }
    }
}

ملحق شدن به گروه‌هاي مخاطب

ملحق شدن به يك گروه مخاطب مي‌تواند از ايجاد آن دشوارتر باشد. حتي اگر ما داراي يك گروه مخاطب نا امن باشيم، همچنان بايد به ايجاد اعتبارنامه، اعتبارنامه‌هاي خالي، و ارسال اين اعتبارنامه‌ها به گروه مخاطبي كه در تلاش براي ملحق شدن به آن هستيم، بپردازيم.

پس از آن كه ما صاحب يك آگهي گروه مخاطب شديم، بايد فرايند ايجاد تمامي اعتبارنامه‌هاي مورد نياز و ملحق شدن به گروه را انجام دهيم. قبل از آن كه نگاهي به متد joinGroup() بياندازيم، اجازه دهيد نگاهي به يكي از كلاس‌هاي مورد استفاده‌ي آن، كلاس MembershipService، داشته باشيم. سه متد در MembershipService وجود دارد كه ما به آنها علاقه‌منديم، به خصوص apply()، join()، و resign(). ما نوع اعتبارسنجي مورد نظر خود را به متد apply() مي‌فرستيم، و اگر آن نوع پشتيباني شود، آن به ما يك Authenticator بر مي‌گرداند. ما از اين Authenticator به منظور ملحق شدن به يك گروه استفاده مي‌كنيم. ما آن را به عنوان يك آرگومان به متد join() مي‌فرستيم، و آن اعتبارنامه‌هاي ما را اعتبارسنجي مي‌نمايد. هنگامي كه يك مخاطب خواهان ترك يك گروه باشد، فراخواني resign() او را به هدف خود مي‌رساند.

حالا نگاهي به متد joinGroup() مي‌اندازيم:

private void joinGroup()
{
   //Assuming myPeerGroup has been instantiated
    //before calling this method.
    System.out.println("Trying to join the peer group");
    try
    {
        //Create the document that will identity this peer.
        StructuredDocument identityInfo = null;
            //No identity information required for our group.

        AuthenticationCredential authCred =
          new AuthenticationCredential(
            myPeerGroup, //Peer group that it is created in
            null, //authentication method. );
        MembershipService membershipService =
           myPeerGroup.getMembershipService();
           Authenticator auth = membershipService.apply(authCred);

        //See if the group is ready to be joined.
        //Authenticator currently makes no distinction between
        //failed and unfinished authentication.
        if( auth.isReadyForJoin() )
        {
            Credential myCred = membershipService.join(auth);
            System.out.println("Joined myPeerGroup");
            System.out.println("Group id: " +
                myPeerGroup.getPeerGroupID() );
        }
        else
        {
            System.out.println("Unable to join the group");
        }
    }

    catch (Exception e)
    {
        System.out.println("An error occurred");
        e.printStackTrace();
    }
}

 

اكنون كه با موفقيت به گروه ملحق شديم، ما قادريم خدمات ارائه شده اين گروه مخاطب را به كار ببريم و پيام‌هايي را به اعضا ارسال نماييم. در هنگام توسعه‌ي برنامه‌هاي كاربردي P2P، تفكر در مورد موقعيت مرزهاي گروه مخاطب شما را در اداره‌ي طولاني‌مدت ياري خواهد داد. به خاطر داشته باشيد كه مرزهاي گروه مخاطب مي‌تواند شبكه‌هاي بسياري را پوشش دهد.

فرايند الحاق مي‌تواند در ابتدا دلسردكننده به نظر آيد، اما چند بار كه آن را انجام داديد به نحوي دلپذير آسان خواهد شد. اكنون امكان استفاده از متدهاي مختلف براي ايمن ساختن يك گروه مخاطب وجود دارد – پيچيدگي فرايند الحاق بستگي به نوع اعتبارسنجي دلخواه شما دارد. من در اينجا اين متدها را مورد بررسي قرار نمي‌دهم. در قسمت 2، من در مورد ابزاري بحث خواهم كرد كه مي‌تواند براي تجريد تقريبا كامل گروه‌هاي مخاطب از كد برنامه مورد استفاده قرار گيرد.

 

لوله‌ها

چنان كه قبلا توضيح داده شد، يك لوله در واقع يك كانال مجازي از ارتباط ميان دو مخاطب است. لوله‌ها مي‌توانند براي افراد تازه‌كار گيج‌كننده باشند چرا كه مبتديان سعي مي‌كنند آنها را به مفاهيمي كه از قبل در ذهنشان وجود دارد ربط دهند -  سوكت‌ها. هنگامي كه من در مورد لوله‌ها بحث مي‌كنم، به خاطر داشته باشيد كه آنها بسيار بيشتر از سوكت‌ها مجرد (abstract) هستند.

در بنيادي‌ترين حالت، دو نوع لوله وجود دارد؛ لوله‌هاي ورودي و لوله‌هاي خروجي. برنامه‌هاي كاربردي از لوله‌هاي ورودي براي دريافت اطلاعات، و از لوله‌هاي خروجي به منظور ارسال اطلاعات استفاده مي‌نمايند. لوله‌ها مي‌توانند در دو حالت ارتباطي مورد استفاده قرار گيرند:

·          لوله‌هاي انتشار واحد يا Unicast (نقطه به نقطه): اين لوله‌ها يك لوله خروجي را به يك لوله ورودي واحد متصل مي‌نمايند، اما يك لوله ورودي واحد مي‌تواند پيام‌ها را از لوله‌هاي خروجي مختلف دريافت نمايد.

·          لوله‌هاي انتشار عمومي يا Propagate: اين لوله‌ها يك لوله خروجي واحد را به تعداد زيادي لوله ورودي مختلف متصل مي‌كند.

 لوله‌ها يك ابزار غير قابل اعتماد، تك‌جهتي، و ناهمگام ارتباطي محسوب مي‌گردند. پياده‌سازي‌‌هاي بهينه شده‌ از لوله‌ها وجود دارند كه قابليت اطمينان، قابليت‌هاي دو جهتي، و انتقال ايمن را فراهم مي‌نمايند.

براي ايجاد يك لوله، نخست شما مي‌توانيد يك آگهي لوله را ايجاد نماييد و آن را منتشر سازيد. آن گاه شما نيازمند دريافت سرويس لوله از گروه مخاطب و استفاده از آن براي ايجاد لوله هستيد. هر لوله داراي يك ID لوله مربوط به خود است، كه براي برقراري ارتباط با آن مورد استفاده قرار مي‌گيرد.

براي ايجاد يك ID لوله جديد، ما از IDFactory در بسته net.jxta.id استفاده مي‌كنيم. اينجا نمونه‌اي از چگونگي ايجاد و چاپ ID را مشاهده مي‌نماييد:

 ID id = IDFactory.newPipeID( peerGroup.getPeerGroupID() );
    System.out.println( id.toURI() );

 توجه: peerGroup گروه مخاطبي است كه شما خواهان ايجاد لوله براي آن هستيد.

 

بنابراين دو لوله مي‌توانند با يكديگر ارتباط برقرار نمايند، آنها بايد از ID لوله‌هايي كه خواهان برقراري ارتباط با آنها هستند آگاهي داشته باشند. چند راه براي حصول اطمينان از اين كه هر دو از اين اطلاعات آگاهي دارند وجود دارد: 

·          هر دو لوله در يك آگهي لوله يكسان از يك فايل خوانده شوند

·          ID لوله درون برنامه‌ها به صورت hard كدنويسي شده باشد

·          انتشار و شناسايي ID لوله در زمان اجرا

·          ID لوله از يك ID مشهور توليد شده باشد (در قسمت 2 مطرح شده است)

 

اگر شما كار ايجاد لوله‌هاي ورودي را انجام مي‌دهيد، دو رويكرد نخست مي‌تواند خطرناك باشد، زيرا بيش از يك مخاطب مي‌تواند يك لوله‌ي ورودي را از آگهي لوله يكسان ايجاد نمايد، كه اين امر منجر به برقراري ارتباط شما با مخاطب اشتباه مي‌گردد. اگر شما از تكنيك سوم استفاده مي‌كنيد و داراي يك ساز و كار براي تشخيص لوله‌ي معين از يك مخاطب دلخواه هستيد، اين مشكل نبايد رخ بنمايد.

براي يك مخاطب جهت تشخيص يك آگهي لوله از ديگري، لازم است كه برخي چيزها را در مورد محتواي آگهي بداند؛ معمولا، آن از صفت Name آگاه است. در هنگام ايجاد آگهي‌هاي لوله، به خاطر داشته باشيد كه چگونه ساير مخاطبان به شناسايي لوله‌هاي ايجاد شده توسط شما خواهند پرداخت. چيز ديگري كه در هنگام استفاده از اكتشاف براي يافتن لوله‌ها بايد حتما مد نظر قرار بگيرد طول عمر آگهي براي انتشار يافتن است. به صورت پيش‌فرض، آگهي‌ها به مدت 365 روز در كش محلي و 2 ساعت در كش راه دور باقي مي‌مانند. اگر شما آگهي‌هاي لوله جديد ايجاد مي‌كنيد، در اين صورت حتما به كاهش اين مقادير نياز خواهيد داشت.

پس از آن كه آگهي انتشار يافت، ما از سرويس لوله براي ايجاد لوله استفاده مي‌كنيم. به علاوه، يك آگهي لوله نيازمند ايجاد شدن و انتشار يافتن براي لوله جديد ايجاد شده است.

به كد زير كه يك لوله ورودي جديد را ايجاد مي‌نمايد و آگهي را انتشار مي‌دهد توجه كنيد (توجه: در قسمت 2، من يك تكنيك كه ID لوله را از يك ID مشهور به منظور تقيد به لوله توليد مي‌كند مورد بحث قرار مي‌دهم، اين تكنيك باعث مي‌گردد كه ما مجبور به منتشر ساختن آگهي لوله نباشيم.):

 

private void   createPublishInputPipe(PeerGroup peerGroup)
{
    System.out.println("Creating new input pipe advertisement");
    //We need to create a new PipeId, create an InputPipe then
        //publish it
    DiscoveryService discoService =
        peerGroup.getDiscoveryService();

    //Get the pipe service for the peer group
    PipeService pipeService = peerGroup.getPipeService();
 

    //Create the advertisement for the pipe
    PipeAdvertisement pipeAdv =
        (PipeAdvertisement) AdvertisementFactory.newAdvertisement(
            PipeAdvertisement.getAdvertisementType() );

    //We want a point-to-point pipe
    pipeAdv.setType( PipeService.UnicastType );
    ID pipeId = IDFactory.newPipeID( peerGroup.getPeerGroupID() );
    pipeAdv.setPipeID( pipeId );       
    pipeAdv.setName( "JxtaDemoPipe" );
    pipeAdv.setDescription( "Jxta demo pipe example" );
              

    try
    {

        //Create the input pipe and register the listener
        //pipeMessageListener assumed to be initalized
        pipeService.createInputPipe(pipeAdv,
            pipeMessageListener );

        //Now let's publish the pipe in the peerGroup
        discoService = peerGroup.getDiscoveryService();

        //DEFAULT_PIPE_LIFETIME is static class (type long)
              //variable value = 1000*60*5 = 5 minutes

        //Publish locally
        discoService.publish( pipeAdv, DEFAULT_PIPE_LIFETIME,
            DEFAULT_PIPE_LIFETIME );

        //Publish to other peers
        discoService.remotePublish(pipeAdv,DEFAULT_PIPE_LIFETIME);
    }

    catch (IOException e)
    {
        System.out.println("IOException occurred");
        e.printStackTrace();
    }

    System.out.println("Input pipe published locally/remotely.");

}

 

در مثال فوق، يك آگهي لوله جديد با يك ID لوله جديد ايجاد شده است. آن با استفاده از سرويس اكتشاف و با طول عمر 5 دقيقه به صورت راه دور و محلي انتشار مي‌يابد. حالا كه ما مخاطب را براي دريافت پيام‌ها تنظيم نموديم، مخاطب ارسال كننده مي‌تواند آگهي لوله را شناسايي كرده و به آن مقيد (bind) گردد. در بخش بعدي، من در مورد نحوه‌ي شناسايي يك آگهي بحث مي‌كنم؛ از آنجايي كه ما نام لوله را مي‌دانيم، از اين مطلب براي شناسايي لوله استفاده مي‌كنيم.

اين پياده‌سازي‌هاي ساده‌ي لوله براي برنامه‌نويسان برنامه‌هاي كاربردي مطلوب نيست. استفاده از آنها دشوار است و هيچ قابليت اطميناني فراهم نمي‌سازند. در قسمت 2، من به بررسي پياده‌سازي‌هاي مفيدتر لوله خواهم پرداخت. براي مثال، JxtaBiDiPipe مي‌تواند براي پيام‌هاي دو جهتي مورد استفاده قرار گيرد، همچنين JxtaSockets، هنگامي كه شما برنامه‌هاي كاربردي خود را ايجاد مي‌نماييد، در مورد اين كه به چه كاركردهايي از لوله‌هايتان نياز داريد فكر كنيد و به دنبال يك پياده‌سازي كه به خوبي با آن نيازمندي‌ها مطابقت داشته باشد بگرديد. در قسمت 2، من JxtaSockets را مورد بحث قرار خواهم داد و آنها را به كار خواهم برد، بنابراين حتما نگاهي به برخي از مشخصه‌هاي جالب آنها بياندازيد.

 

آگهي‌ها

آگهي‌ها ابزاري براي توصيف و انتشار منابع به حساب مي‌آيند. هنگامي كه آگهي‌ها انتشار يافتند، آنها داراي يك طول عمر مربوط به خود هستند، كه اين امر امكان شناسايي آگهي‌هاي كهنه و حذف آنها را فراهم مي‌آورد. همان گونه كه قبلا مطرح گرديد، طول عمر پيش‌فرض، در پياده‌سازي رايج، 365 روز براي منابع انتشار يافته‌ي محلي و 2 ساعت براي منابع انتشار يافته راه دور است. در هنگام ايجاد و انتشار آگهي‌ها اين نكته را به خاطر داشته باشيد. گاهي اوقات ممكن است كاستن يا حتي افزايش دادن اين مقادير پيش‌فرض مفيد واقع شود.

در هنگام يافتن آگهي‌ها، Jxta از انتشار عمومي براي ارسال پيام‌ها به زيرشبكه محلي كه مخاطب در آن قرار دارد استفاده مي‌كند. اگر شما نيازمند ارسال پيام‌ها به خارج از اين ناحيه هستيد، اطمينان حاصل كنيد كه به يك مخاطب rendezvous متصل هستد، مخاطبي كه پيام‌ها را براي شما ارسال خواهد نمود. همچنين، اگر شما در پشت يك فايروال قرار داريد يا اگر شبكه شما از Network Address Translation استفاده مي‌كند، در اين صورت براي برقراري ارتباط با مخاطبان خارجي، شما همچنين ناچار به تعيين يك مخاطب relay خواهيد بود. براي يافتن منابع مخاطب، ما از سرويس اكتشاف پلاتفرم Jxta استفاده مي‌كنيم، كه يك ابزار ناهمگام يافتن منابع محسوب مي‌گردد. ما پرس و جوهاي اكتشاف را ارسال مي‌كنيم و يك سري پاسخ‌ها را گردآوري مي‌نماييم.

دو رويكرد كار يافتن آگهي‌ها را انجام مي‌دهند:

1- يك فراخواني براي يافتن آگهي‌هاي راه دور صورت دهيد، آن گاه درون كش محلي را براي آگهي‌هاي يافت شده نگاه كنيد

2- يك فراخواني براي يافتن آگهي‌هاي راه دور صورت دهيد و يك گوش دهنده را براي فعال شدن در هنگام دريافت شدن يك آگهي ثبت نماييد.

 

حالا بياييد نگاهي به نحوه ايجاد شدن درخواست‌هاي اكتشاف بياندازيم. در اينجا امضاهايي براي متدهاي getRemoteAdvertisement() در رابط net.jxta.Discovery.DiscoverService مي‌بينيد:

 

int getRemoteAdvertisements(String peerid, int type, String attribute, String value, int threshold)
int getRemoteAdvertisements(String peerid, int type, String attribute,String value, int threshold, DiscoveryListener listener)