Clients send key data whenever a key goes down or goes up and then the server processes the data and sends the data back to the clients which update the player position.
Clients send key data whenever a key goes down or up and also update their representation with what they think would happen, then update their data using the authoritative server data.
Clients send key data whenever a key goes up or down, predict the outcome, then when the server answer comes back, simulate what would have happened if you had known that the client was in this state and then had pressed the keys.
Player movement should be transferred to the server at a specific rate (every 100 ms?), complete with client-side prediction.