This is done with two messages: bitfield and have.
After two peers perform a handshake, they can optionally send bitfields as their first messages, which compactly represent all of their completed blocks.
Once a peer successfully downloads and verifies a block, they broadcast a have message to all of their connected peers, letting them know which block they just completed.