To expand on what kasperd says in a comment. This sort of thing should be handled in the protocol. This would typically be done by adding message authentication code (MAC) in the traditional encrypt-then-mac paradigm or using authenticated encryption.
So then instead of doing if (client.aeskey != server.aeskey), print Error
, you would be doing if (MAC(received_ciphertext, correct_key) != received_mac), print Error
(in practice your crypto library that has built in authentication checks would do this for you and return an error).
As far as
a way for me to know what AES key the client actually used
goes. There isn't a reliable way without additional assumptions (e.g., we assume that at most 2 bits were flipped).
We traditionally think of these designs as checking for modifications of the ciphertext, but if the incorrect key is used (say due to errors in the storage mechanism or whatever), it would also detect that. The benefit of doing this is you don't have to decrypt before realizing that something is wrong. Instead, you check the MAC and if that fails, you don't decrypt at all.
There are some practical things you should take into consideration. Your best bet would be to use a commercial library. The right one will depend on your setup and needs.
Warning, the absolute wrong way to do this would be to check the padding at the end of the plaintext (assuming you are using mode like CBC that requires padding), and then return an error if the padding is incorrect. This leads to a devastating attack known as a padding oracle attack.