Как я понимаю причину глюка:
- TCP_Server создает "серверный" сокет и назначает ему процедуру чтения поступающих данных
- при каждом входящем подключении создается "клиентский" сокет (их может быть много) и этому клиентскому сокету опять же назначается процедура, которая будет принимать присланные клиентом данные. Реализовано это таким образом, что каждый клиент получает ту же процедуру, которая назначалась в коде выше:
- поскольку THITCP_Server._work_doClose закрывало только "серверный" сокет, "клиентские" сокеты по прежнему могли вызывать процедуру чтения, так как они уже знали её адрес, а объект, в котором она находится (THITCP_Server) всё ещё существует. Именно поэтому не работала отправка данных сервером ("серверный" сокет, отправляющий данные, закрыт).
С чего можно сделать такие выводы:
1) Если принять твою последнюю поправку к THITCP_Server._work_doClose, то также нужно поправить описание к точкам
- doClose - отключает всех присоединенных клиентов и запрещает входящие соединения (останавливает сервер)
- doCloseAll - отключает всех присоединенных клиентов, но не останавливает сервер
2) Вижу одну реальную задачу, когда может применяться старый подход: если серверу нужно иметь не больше указанного количества клиентов. Тогда:
- делается счетчик подключений; если количество равно максимальному, прекращается прием новых подключений, но уже подключенные клиенты продолжают обслуживаться;
- делается счетчик отключений; если клиент отключается - сервер опять начинает принимать входящие подключения;
Но в этом случае нужно, чтобы по doClose не уничтожался "серверный" сокет, а выставлялся флаг запрета входящих подключений в процедуре приема (то есть, не обрабатывать FD_ACCEPT, но обрабатывать остальные команды). Всё это требует дополнительных тестов, так что твой вариант, наверное, на данный момент более предпочтительный.