If you use dup(), the two descriptors are somewhat connected: the second file descriptor uses the same underlying file description. That means, for example, if you use lseek() with an offset of 100 on one descriptor, and then read from the other one, you'll read starting from offset 100.

If you open() two separate descriptors, however, a seek on one descriptor won't affect the other one at all, and you can read from offset 100 in one file and offset 200 in the other file, without interference.