Whenever the user on a given node wants to find an object, Gnutella
sends a QUERY message for the object—for example, specifying the file’s
name—to its neighbors in the graph. If one of the neighbors has the
object, it responds to the node that sent it the query with a QUERY
RESPONSE message, specifying where the object can be downloaded
(e.g., an IP address and TCP port number). That node can subsequently
use GET or PUT messages to access the object. If the node cannot resolve
the query, it forwards the QUERY message to each of its neighbors (except
the one that sent it the query), and the process repeats. In other words,
Gnutella floods the overlay to locate the desired object. Gnutella sets a
TTL on each query so this flood does not continue indefinitely.
In addition to the TTL and query string, each QUERY message contains
a unique query identifier (QID), but it does not contain the identity of
the original message source. Instead, each node maintains a record of the
QUERY messages it has seen recently: both the QID and the neighbor that
sent it the QUERY. It uses this history in two ways. First, if it ever receives
a QUERY with a QID that matches one it has seen recently, the node does
not forward the QUERY message. This serves to cut off forwarding loops more quickly than the TTL might have done. Second, whenever the node
receives a QUERY RESPONSE from a downstream neighbor, it knows to
forward the response to the upstream neighbor that originally sent it the
QUERY message. In this way, the response works its way back to the original
node without any of the intermediate nodes knowing who wanted to
locate this particular object in the first place.