If an attack (DoS & DDoS) involves thousands of bots, how can the server distinguish them from legitimate clients?
It's going to vary for every single attack. With DoS attacks, you can looks for attributes that are different than "real" requests, say values that are out of range, or the lack or specific format of a particular piece of data like a user-agent or referer in a HTTP request.
Generally speaking for DDoS attacks, if the traffic gets to the server, you've lost, and it doesn't matter. DDoS attacks are purely designed to choke resources and the most common bottleneck is the network bandwidth. You can potentially identify characteristics of a DDoS attack, but it almost always needs to be identified and managed upstream so the traffic never reaches your servers.