Есть сервер на Qt/c++, он слушает определенный порт и принимает с него данные. Когда к нему поступают какие-нибудь данные, они выводятся на консоль. Однако параллельно с этим мне бы хотелось в консоли осуществлять управление сервером. Т.е. необходимо принимать команды. Я выделяю отдельный поток на чтение команд и в нем работает такая функция:
std::string readCommand()
{
std::string command;
getline(std::cin, command);
return command;
}
Но при этом сервер перестает принимать данные и отвечать на них. Как можно распараллелить это?
Сервер запускается, работает без ГУИ (в терминале). В качестве клиента использую telnet.
OS: Mac OS X High Sierra Qt 5.9.2
Сокеты работают асинхронно, через очередь событий.
Как работает эта очередь:
Внутри функции QCoreApplication::exec()
, которую вы в обязательном порядке вызываете из main()
, крутится вечный цикл.
На каждой итерации этого цикла производится проверка системной очереди сообщений, в которую операционная система заботливо складывает все уведомления приложению от системы, драйверов и других программ. Данные, полученные сокетом, также посылаются в виде уведомлений.
Если очередь непуста, из неё извлекается очередное сообщение.
На основании данных в сообщении определяется QObject
-получатель, в метод QObject::event()
которого необходимо передать данное сообщение.
Реализация QObject::event()
конкретного объекта может делать всё что угодно. QTcpSocket
, к примеру, пишет новоприбывшую порцию данных во внутренний буфер и испускает сигнал readyRead
.
После возврата управления из QObject::event()
возвращаемся в п. 3.
Если же очередь пуста, засыпаем до прихода сообщения, затем возвращаемся в п. 3.
Как видите, для получения данных из сокета надо хотя бы иногда возвращать управление в обработчик очереди событий. Иными словами, возвращаться из функций, которые вы непосредственно не вызывали.
Вы же блокируете выполнение программы вызовом std::getline()
. То есть пока пользователь не введёт в консоль строку, сервер и его очередь сообщений будут простаивать.
Теперь решение проблемы. Есть два способа: один как правильно и один чтоб просто работало:
первый способ — убрать консоль из сервера и заменить её на именованный канал, к которому можно будет подключаться любым из уже существующих терминальных клиентов (тем же Putty). Избавление от интерфейса пользователя позволит отвязать сервер от пользователя и запускать его как службу, как любую нормальную взрослую программу-сервер.
второй способ (если вас не устроил первый — напишите в комментариях почему) — разнести сокет и блокирующее чтение из консоли по разным потокам. Переносить при этом стоит именно сокет (вызвав для этого QTcpSocket::moveToThread()
перед connectToHost()
), так как весь UI привязан к главному потоку.
Частный дом престарелых в Киеве: комфорт, забота и профессиональный уход
В функции matrix_sum видает ошибку , подскажите что я не так написал?
Всем доброго времени сутокОтлавливаю клики мыши, затем преобразую каждый клик, который является центром примитива, в некоторый набор точек