Your instincts are entirely correct: it's a bad idea to have a large complex program run as root, because their complexity makes them hard to trust.
But, it's also a bad idea to allow regular users to bind to privileged ports, because such ports usually represent important system services.
The standard approach to resolving this apparent contradiction is privilege separation. The basic idea is to separate your program into two (or more) parts, each of which does a well-defined piece of the overall application, and which communicate by simple limited interfaces.
In the example you give, you want to separate your program into two pieces. One that runs as root and opens and binds to the privileged socket, and then hands it off somehow to the other part, which runs as a regular user.
These two main ways to achieve this separation.
A single program that starts as root. The very first thing it does is create the necessary socket, in as simple and limited a way as possible. Then, it drops privileges, that is, it converts itself into a regular user mode process, and does all other work. Dropping privileges correctly is tricky, so please take the time to study the right way to do it.
A pair of programs that communicate over a socket pair created by a parent process. A non-privileged driver program receives initial arguments and perhaps does some basic argument validation. It creates pair of connected sockets via
socketpair()
, and then forks and execs two other programs that will do the real work, and communicate via the socket pair. One of these is privileged and will create the server socket, and any other privileged operations, and the other will do the more complex and therefore less trustworthy application execution.