the other answers on this thread are totally legit but I believe I can add a bit to it.
Let us discuss what a completion port IS, the way I understand it.
A completion port is an event sink. That is, an event occurs, a completion port gets notified.
Now, there is of course a large taxonomy of events. Completion port is well-suited for events of a particular kind: IO completions. There is a patent by Cutler and gang written in surprisingly human-readable language, that describes how IOCP integrates with NT kernel.
Recapping: a completion port is an event sink well-suited for receiving notifications of IO completions.
Now let's go back to OP's question:
How do I setup IOCP sockets for multiple listeners (on different ports)?
Your event is a completion of a a previously issued AcceptEx() call. It typically is a connect() call on a client side but also could be someone disabling your NIC.
you first decide if you want the connects on the same port to be processed concurrently or serially. Also you need to decide whether you want to have connects on different ports to be processed concurrently or serially.
I see three potential approaches:
- all connection completions are serialized
CreateIOCompletionPort upfront once, BindIOCompletionCallback to it for every listener, one worker thread that calls GetQueuedCompletionStatus as RbMm described
- connection completions of same listener (on same port) are serialized, but connection completions on different ports are concurrent
you have to create one completion port per listener and spin up a worker that will GetQueuedCompletionStatus()
- all connection completions are concurrent
You can have one completion port but you spin up multiple threads to call GetQueuedCompletionStatus()
You are not necessarily restricted with having thigs as I described above. Completion ports are clever so you can go with one port and multiple waiters, and then waiters acquire per-listener locks for serialization. Completion port machinery in kernel will figure out that you blocked and release other waiters when appropriate.
Recapping: first, you decide how concurrent you want to be. Then you choose how many completion ports you need to have.