Я бы предположил, что неоткрытие портов это просто симптом того, что какой-то из более ранних шагов инцииализации программы под доменной учеткой прошел неуспешно. Или весь остальной функционал работает штатно ?
WI-FI каждому устройству отдает отдельный "серый" IP - https://ru.wikipedia.org/wiki/%D0%A7%D0%B0%D1%81%D...
В тот момент когда запрос от пользователя с "серым" IP проходит через пограничное с "настоящим" Интернетом устройство (а это может быть сам WI-FI роутер, а может быть какое-то другое устройство более вышестоящего провайдера) происходит NAT и запрос выходит уже с "белым" IP-адресом роутера и с уникальным клиентским портом и в таком виде идет к серверу.
Почитайте что-нибудь про NAT - станет гораздо понятнее.
P.S. Если у Вас сервер не в Интернете, а в той же локальной сети, что и WI-FI, то сервер будет видеть "серые" адреса и каждый клиент будет приходить со своим уникальным IP.
У каждого подключения уникальная пара "клиентский IP-клиентский порт". А вот выяснять, за каким портом находится какой пользователь - это функции Вашего приложения. Собственно для этого и происходит первым шагом аутентификация во всех популярных протоколах - чтобы за один роутером (и соответственно одинм IP) могли сидеть сотни человек и все они имели свой собственный профиль и привилегии в программе.
Да, у сервера будет LISTENING-сокет на порту 8888, который будет открыт по команде из программы BIND( ), например, пусть его идентификатор (выданный нам опер.системой) будет равен 120.
В момент подключения первого клиента программе будет сигнализировано, что есть входящее подключение и после того, как программа даст команду ACCEPT(120, ...) ей будет возвращен идентификатор первого INCOMING-сокета, пусть будет 200.
Теперь серверная сторона должна:
1) ожидать новых подключений на сокет 120
И
2) ожидать данных с сокета 200.
Как только произойдет либо первое либо второе операционная система просигнализирует программе.
Пусть первым пришло подключение от второго клиента, тогда ACCEPT(120, ...) и ОС возвращает нам еще один, третий идентификатор - назовем его 240.
Теперь серверная сторона должна:
1) ожидать новых подключений на сокет 120
И
2) ожидать данных с сокета 200
И
3) ожидать данных с сокета 240.
Пусть поступили данные на сокет 200 - считываем их командой RECV(200, ...) и все, что получили, отправляем на сокет 240 командой SEND(240, ...)
Пока Вы не поймете, что ДП - это однонаправленное путешествие по графу состояний, Вы не сможете приводить задачи к решаемым методом ДП.
Обычно обучение ДП начинают с любой задачи на прямоугольнике с движением вверх и вправо - например, пройти по шахматной доске только вверх и вправо, набрав максимальную сумму из расположенных в ячейках чисел. Здесь пространство состояний очень легко наблюдаемо - это текущая клетка, и сам орграф тоже понятен - в большую часть клеток можно прийти только снизу или справа. Взгляните в этой задаче на доску повернув ее на 45 градусов и увидите тот самый граф.
Затем мысленно попытайтесь предстваить задачу с асфальтовыми заплатками в виде такой же доски.
Предполагаю, что по разному написали тех.задание те люди, которые принимали решение о возможностях сервиса, ибо сам по себе Ваш вопрос не стандартизован ни в одном стандарте, т.е. каждый сервис волен поступать по своему.