How does a P2P network "work," and how is it different from the conventional client/server or multitiered networks we're so used to? Other than the fact that there is typically no centralized mega-server involved, there seems to be very little difference to casual observers. The following JXTA 2-based explanation should help to clarify the concepts.
In a P2P network, everything you'd want to access (called resources) are owned and managed by peers, as illustrated in Figure 1:
Figure 1. Shared resources managed by peers in a P2P network
Resources can be almost anything manageable by a computer. They typically include files (as in file sharing P2P applications), devices (disks, printers, and so on), privileged connections (such as to a bank of super computers), databases, computing power, memory, bandwidth, and so on. The peers in this network can come and go at any time (such as when a user on the network turns off his computer), taking the resources that they share with them. P2P applications are all based on this ad hoc ability for a group of peers to share resources.
The primary role of a P2P network, such as the JXTA network, is to provide a best attempt to get you the resource you request, anytime you demand it. Note that it is a best attempt and not a sure thing, because the peer or peers that manage the resource you want may simply not be available. This is often referred to as the non-deterministic nature of P2P systems.
How does a P2P network "find" the resource you requested? In JXTA 2, this action is called resolving a query. A query is your demand for some resource. The JXTA 2 component that enables query resolution is called the resolver. Most cornerstone components in JXTA 2 (that is, pipes and routers) rely on the resolver. Other P2P technology may have identical concepts with different names. Figure 2 illustrates the resolution of queries in JXTA 2:
Figure 2. Query resolution in JXTA 2
In this figure, we can see a network of five peers: EP1 through EP5. Each of the peers manages a shared resource. EP2 in particular owns shared resource H. In this scenario, EP1 queries for resource H. It sends the query to the JXTA network resolver. The resolver resolves the query, and the response to EP1 comes from EP2 directly as a result.
Thus far, we seem to be dragging our feet on the question of how the P2P network "finds" a demanded resource or, equivalently, how JXTA 2 resolves a query. But here lies the crux of a P2P network, and the specific mechanism may be completely different for different networks. Theoretically, if every peer on the network receives your query at the same time, one or more of them will respond with "I've got the resource." Practically speaking, this is "network flooding" and is completely unmanageable beyond a small network consisting of a handful of peers. Therefore, the "magic" of P2P networks depends on the network's ability to achieve the very same result -- the ability to resolve a query -- without exhausting the network's resource and hampering scalability.
There are probably an infinite number of ways to implement the resolver functionality. The most active area of research at this time, however, centers on the concept of distributed data structures. We are familiar with data structures such as hash tables, lists, and trees; most of the time, these data structures are created, used, and destroyed within the memory space of a single machine. Distributed data structures are data structures that are maintained in a distributed fashion between a network of machines. In fact, JXTA 2's architecture maintains a variation of a DHT consisting of all the shared resources in the entire JXTA network. Actually, indices of hash keys related to the resources are stored throughout the network, while the resources themselves (the hash values) are not moved from the owning peer. Therefore, the action of resolving a query is reduced to a "hash" against the keys in this DHT, resulting in the location of the corresponding peer. See Rendezvous peerview and RPV walker for more details on how this is implemented in JXTA 2.
Once a query is resolved, the next step is entirely application specific. In the case of a file sharing application, the peer responding to the query has the requested file, and the requesting peer may initiate an FTP or HTTP file transfer operation to obtain the file. This may occur out-of-band with respect to the P2P network. In the case of JXTA's internal components -- say the pipe service -- further queries may need to be resolved (binding a peer to an endpoint) and the application draws on the service of the resolver again.
It is important to realize the vital importance of the resolver to a P2P network. In fact, layered protocol P2P networks like JXTA 2 rely on the resolver to deliver messages over their set of transports. This is because a route to a destination peer can be viewed as a P2P network resource. And because any peer can come and go at any time, a previously valid route to a destination peer may become invalid in a split second. A message being routed to the destination peer using the stale route will face delivery failure. In this case, JXTA's router component will -- in real time -- query the resolver for a new route to the destination peer.