There are two problems here. One is to synchronize wall clock time, either by using a centralized reference (say ntp), or to guessing from the round-trip time between the clients. The other is synchronizing simulation time, which is solved by using a lookahead. If player 1 presses a button at simulation time T, the change is scheduled to take place at time T+D where D is sufficiently large to be sure that this information has been transmitted to player 2.
Ok, but don't I need to make sure that player 2 received that message?
(I read that multiplayer games usually use UDP and not TCP...)