Почему сокеты sfml не работают внутри класса?
Вчера пол вечера убил на написание класса ServerManager, который бы обрабатывал входящие сообщения и подключения. Всё было написано в абсолютном соответствии с документацией sfml, однако происходило вот что: после первого подключения и добавления этого подключения в SocketSelector сервер переставал принимать вообще какие-либо сигналы, т.е. невозможно было ни повторно подключиться, ни написать сообщение, метод wait просто не сигнализировал о наличии сокетов, готовых к передаче сообщения. Listener как-будто бы тоже не слышал новые подключения после самого первого из них. Я не мог понять, в чём проблема. Сейчас вот решил ради интереса переписать в примитивном виде эту логику в цикл while() внутри main`а, и... Всё работает, как надо, селектор сигнализирует о наличии новых подключений или сообщений, всё обрабатывается. Хотя логика, повторюсь, идентична тому, что написано в классе. И я всё же нашёл то самое ключевое различие: внутри класса я храню не vector sockets, а vector users, где User - мой класс, внутри которого - имя юзера и TcpSocket* socket; Т.е. фактически, тоже самое, что в первом случае, но внутри класса User, в котором дополнительно лежит имя. В первом случае - прекрасная работа, во втором - селектор просто ничего не ловит. Приведу два примера кода, первый - где, всё работает (с вектором указателей), второй - где проходит лишь первое подключение, а дальше - тишина:
Рабочий вариант с вектором TcpSocket*
while (true)
{
if (selector.wait())
{
if (selector.isReady(listener)) //Поключение
{
TcpSocket *socket = new TcpSocket;
listener.accept(*socket);
Packet packet;
socket->receive(packet);
string str;
packet >> str;
cout << "NAME: " << str << endl;
sockets.push_back(socket);
selector.add(*socket);
}
else
{
for (auto & var : sockets)
{
if (selector.isReady(*var)) //Приём сообщений
{
Packet packet;
var->receive(packet);
string str;
packet >> str;
cout << "MSG: " + str << endl;
}
}
}
}
}
С классом User
while (true)
{
if (selector.wait())
{
if (selector.isReady(listener))
{
TcpSocket *socket = new TcpSocket;
listener.accept(*socket);
Packet packet;
socket->receive(packet);
string str;
packet >> str;
cout << "NAME: " << str << endl;
User user = User(str, socket); //Создаём нового User (str - имя, socket указатель)
users.push_back(user);
selector.add(*user.getUserSocket()); //getUserSocket возвращает указатель на socket
}
else
{
for (auto & var : users)
{
if (selector.isReady(*var.getUserSocket()))
{
Packet packet;
var.getUserSocket()->receive(packet);
string str;
packet >> str;
cout << "MSG: " + str << endl;
}
}
}
}
}
Скажите, пожалуйста, в чём дело? Как это обойти?
Ответы (1 шт):
Приношу свои извинения, буквально после того, как я задал вопрос, мне удалось найти проблему: Внутри первого блока if (см. 2 пример) происходит создание промежуточной сущности user, которая, хранит указатель на новый сокет. Трагедия в том, что как только блок завершается, сущность уничтожается, вызывается деструктор, который очищает указатель на socket, в связи с чем внутри selector`а образуется мусор, с которым он, само собой, работать не может. Удаление delete socket исправило проблему