Приложението „peer-to-peer“ стана лесно

Казано е, че Kazaa, приложението за споделяне на файлове (P2P), причинява повече мрежов трафик от всяко друго приложение. Уебсайтът Kazaa посочва, че е имал повече от 385 000 000 изтегляния! За сравнение разгледах най-добрите изтегляния на Download.com, в които Ad Aware е посочен като най-популярното изтегляне, само с 117 000 000 изтегляния. От най-добрите 25 изтегляния на Download.com разпознах 11 P2P приложения. Само от тези наблюдения, P2P приложенията очевидно растат по популярност. Но споделянето на файлове не е единственият тип P2P приложение. Повечето операции на типично приложение за незабавни съобщения са P2P. Други примери са форуми и разпределени бази данни. И списъкът просто продължава да расте.

За да създадете P2P приложения като тези, трябва да имате средства за откриване и взаимодействие с други връстници. Повечето трудности, свързани със създаването на P2P приложения, са свързани с поддържане на мрежа от връстници, форматиране и предаване на съобщения, откриване на други връстници и други подобни проблеми. Project Jxta и неговото свързване с Java се справят с тези аспекти на вашето приложение. Използвайки Jxta, можете да се съсредоточите върху приложението си, а не върху общи P2P проблеми.

Jxta е съкратена версия на думата juxtapose,което означава рамо до рамо. Ръководството на програмиста на Jxta определя Jxta като „отворена изчислителна платформа, предназначена за P2P изчисления“. Той не е специфичен нито за никоя платформа, нито за който и да е език за програмиране. Той е създаден в Sun Microsystems и е пуснат в общността с отворен код за поддържане и развитие. Заедно с издаването му беше издадено първоначално внедряване на Java. Фокусирам се върху тази реализация в тази статия, докато обсъждам как да използвам Jxta в Java среда. Също така обхващам шестте най-често срещани операции на Jxta приложения, внедрени в Java, и представям инструментите, от които се нуждаете, за да започнете да пишете свои собствени P2P приложения. След като прочетох тази статия, се надявам, че сте разбрали колко лесно и вълнуващо може да бъде създаването на P2P приложения. P2P приложенията ще продължат да растат не само по популярност, но и в разнообразие,и утре разработчиците трябва да започнат да изучават тези технологии днес, за да останат на върха.

Java и Jxta

Първата стъпка към използването на Jxta е изтеглянето му от страницата за изтегляне на Jxta. Както повечето читатели ще се съгласят, понякога проектите с отворен код могат да бъдат трудни за придобиване и конфигуриране за използване. Jxta е пример за страхотен проект с отворен код, който също е много лесен за изтегляне и използване веднага. Ако имате затруднения и се нуждаете от повече информация за изтеглянето и използването на Jxta, вижте Ръководството за програмист на Jxta.

Когато стартирате за първи път приложение с активирана Jxta от нова директория, ще ви бъде предоставен GUI конфигураторът.

Какво всъщност е връстник? Според Даниел Брукшир (добре познат комисар на Jxta и така нареченият „шампион“), това е „виртуална комуникационна точка“, където различни връстници могат да работят на едно и също устройство. Устройството не е ограничено до компютър; това може да бъде мобилен телефон, сървър или дори елемент, толкова прост като сензор. Има специални връстници, двамата, за които трябва да сме наясно, са рандеву и реле. Рандеву връстник позволява на връстниците да комуникират извън обхвата на локалната подмрежа, а ретранслатор се използва за препредаване на информация чрез защитни стени.

Нека започнем с разглеждането на шестте най-често срещани операции за приложения на Jxta, както са дефинирани в „Разходите за използване на Jxta“ (IEEE Computer Society, септември 2003 г.). Те са изброени по-долу в реда, в който обикновено се появяват.

  1. Стартиране на Jxta: Стартирането на Jxta е доста просто и е просто въпрос на няколко реда код.
  2. Присъединяване към група от връстници: Група от връстници е набор от връстници, имащи общ набор от интереси, които са групирани заедно. В тази статия разглеждам присъединяването към съществуващи групи от връстници и създаването на нови.
  3. Публикуване на реклами: Рекламите, просто казани, са това, което представлява Jxta. Jxta използва реклама, за да открива връстници, групи от връстници и други ресурси по независим от платформата начин. По-късно в тази статия обсъждам четенето, създаването и изпращането на нови реклами.
  4. Отваряне на входна тръба: Тръбата е един механизъм, който връстниците използват, за да комуникират помежду си. Тръбите са „виртуални комуникационни канали “ - виртуални, тъй като потребителите на тръби не знаят действителния адрес на другия връстник. Обсъждам използването на тръби за изпращане на съобщения в раздела на тази статия за тръби.
  5. Откриване на други ресурси от връстници: Преди да можете да общувате с други връстници, първо трябва да намерите такива, които също ще обсъдя.
  6. Отваряне на изходна тръба: Изходните тръби се използват за изпращане на съобщения до други връстници. Има два класа изходни тръби: точка към точка, или един към един, и разпространение, или един към много.

След като вече знаете къде ще ви отведе тази статия, нека започнем нашето пътешествие.

Групи от връстници

Групите от връстници са просто колекция от връстници с някакъв набор от общи интереси. Групите от връстници, като връстниците, могат да предоставят услуги, но услугата за група от връстници не е задължително да зависи от конкретен партньор, който изпълнява заявки към него. Докато един партньор в групата предоставя услугата, тя е достъпна. Всеки връстник е член на световната група от връстници, а също така обикновено и на нетната група от връстници и може да избере да се присъедини и да напусне други групи по желание. Каква е мотивацията за създаване на групи от връстници? Ето няколко причини:

  • Поддържане на защитен регион: Ако имате защитена група от връстници, връстниците в групата не трябва да излагат своята критична информация.
  • Предоставяне на общи услуги: Обикновено много връстници ще искат да използват / предоставят същите услуги като другите връстници, така че това да се прави в групата просто има смисъл. Например можете да предоставите принтер или услуга за разпределена база данни на всички връстници в групата.
  • Ограничение на обхвата на идентификатора: Имената на тръбите се съчетават с групата, в която са създадени. Ако две тръби имат едно и също име, но не са създадени в една и съща група, тогава няма проблеми с тяхното адресиране.

Нека разгледаме как можем да създадем и да се присъединим към група от връстници. Методите, предоставени от PeerGroupинтерфейса, са изброени по-долу.

  • newGroup(Advertisement pgAdv): обикновено се използва за създаване на инстанция на група, която вече съществува с откритата групова реклама
  • newGroup(PeerGroupID gid, Advertisement impl, String name, String description): обикновено се използва за изграждане на нови групи от връстници
  • newGroup(PeerGroupID gid): Използва за примери съществуваща и публикувани, контролна група само с 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(). Този метод ще насочи рекламата на група от връстници към други връстници. Ако трябва да се уверите, че изпращате рекламата на връстници в друга подмрежа, трябва да сте сигурни, че сте свързани с връстник на срещата. За да направите това, използвайте следния код, ако приемете, че връстникът ви за среща е изправен и конфигуриран правилно:

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(); } } } 

Присъединяване към групи от връстници

Joining a peer group can be more difficult then actually creating one. Even if we have an unsecured peer group, we still must create credentials, empty credentials, and send these credentials to the peer group we are trying to join.

Since we have a peer group advertisement, we need to create all the credentials necessary and join the group. Before we look at the joinGroup() method, let's look at one of the classes it uses, the MembershipService class. There are three methods in MembershipService that we are interested in, specifically apply(), join(), and resign(). We pass to the apply() method the type of authentication desired, and if that type is supported, it returns to us an Authenticator. We use this Authenticator to actually join the group. We pass it as an argument to the join() method, and it verifies our credentials. When a peer wants to leave a group, the call to resign() facilitates this.

Now let's look at the joinGroup() method:

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(); } }

Now that we have successfully joined the group, we are able to employ provided peer group services and send messages to the members. When developing P2P applications, thinking about where you want your peer group boundaries ahead of time will assist you in the long run. Keep in mind that peer group boundaries can span many networks.

The joining process can seem daunting at first, but it is pretty straightforward once you do it a few times. Now it is possible to employ many different methods to secure a peer group—the complexity of the joining process depends on the type of authentication desired. I do not discuss these methods here.

Pipes

As explained earlier, a pipe is a virtual channel of communication between two peers. Pipes can be confusing for beginners because newbies try to relate them to what they already know—sockets. While I discuss pipes, keep in mind that they are much more abstract then sockets.

In the most basic form, there are two types of pipes; input pipes and output pipes. Applications use input pipes to receive information, and output pipes, to send information. Pipes can be used in two addressing modes:

  • Unicast (point-to-point) pipes: These pipes connect one output pipe to a single input pipe, but a single input pipe can receive messages from different output pipes
  • Propagate pipes: These pipes connect a single output pipe to many different input pipes

Pipes are an unreliable, unidirectional, and asynchronous means of communication. Beefed-up implementations of pipes are available that provide reliability, bidirectional capabilities, and secure transit.

To create a pipe, first you must create a pipe advertisement and publish it. Then you need to get the pipe service from the peer group and use it to create the pipe. Each pipe has a pipe ID associated with it, which is used to address the pipe.

To create a new pipe ID, we use the IDFactory in the net.jxta.id package. Here is a sample of how to create and print the ID:

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

Note:peerGroup is the peer group for which you want to create the pipe.

Така че двама връстници могат да комуникират помежду си, те трябва да знаят идентификационните номера на тръбите, с които искат да комуникират. Има няколко начина да се уверите, че и двамата знаят тази информация:

  • И двамата връстници четат в една и съща тръбна реклама от файл
  • Идентификаторът на тръбата е кодиран твърдо в приложенията
  • Публикувайте и откривайте ID на тръбата по време на изпълнение
  • Pipe ID се генерира от добре познат ID