Я пришел из Java, так что это довольно сложно для меня понять. Я пишу клиент-серверную программу, чтобы начать изучать C ++.
ServerSocket server(30000);
while (true) {
ServerSocket new_sock;
server.accept(new_sock);
std::cout << "client connected...\n";
ClientConnectionThread *cct = new ClientConnectionThread(new_sock);
cct->start();
}
Моя проблема возникает, когда я пытаюсь записать в сокет в ClientConnectionThread.
client_sock << someObj;
Exception was caught in cct: Could not write to socket.
Я предполагаю, что после cc-> start (); команда ServerSocket потеряет «область видимости» и будет вытолкнута из стека и автоматически закрыта. Чтобы это исправить, я изменил код на:
ServerSocket server(30000);
while (true) {
ServerSocket *new_sock; <----
server.accept(new_sock);
std::cout << "client connected...\n";
ClientConnectionThread *cct = new ClientConnectionThread(new_sock);
cct->start();
}
Но программа даже не вошла в цикл … без сообщений об ошибках, говорящих мне, почему это не сработало (Конечно, изменяя необходимый код, чтобы принять указатель).
Если не очевидно, что я пытаюсь сделать .. Я ищу создание нового потока на каждом клиентском соединении для обработки каждого клиента. Конечно, потоку понадобится ссылка на сокет для получения и отправки — вот почему я передаю его объекту CCT.
Если вам нужно больше кода, дайте мне знать.
Ваш первый код не работает именно из-за того, что вы сказали. Объект размещается в стеке, но как только он выходит из области видимости, он уничтожается, и, как следствие, закрывается указатель на сокет.
Если вы хотите сохранить объект «живым», вам нужно использовать указатели. Вы поняли это правильно, но упустили важный момент: вы выделять предмет! Для этого вам нужно воспользоваться оператором new
в дальнейшем:
ServerSocket *new_sock = new ServerSocket;
Теперь есть одна загвоздка: на Java ваш объект автоматически освобождается GC, но в C ++ нет сборщика мусора, поэтому вам нужно сделать это вручную. Как только вы закончили использовать объект, вам нужно delete
Это.
delete new_sock;
Это может быть очень сложно, может вызвать много сбоев и даже утечек памяти. Если вы хотите, чтобы поведение было более похожим на Java GC, вы можете использовать shared_ptr
, это автоматически освободит объект (это не так просто, но вы легко найдете больше информации об этом в Google.)
std::shared_ptr<ServerSocket> new_sock = std::shared_ptr<ServerSocket>(new ServerSocket);
server.accept(*new_sock);
(при условии, что вы компилируете под C ++ 11)
Вы могли бы заставить свою первую версию работать, если бы вы передавали копию вместо ссылки ServerSocket в свой поток (если это возможно — для сокета сервера для этого потребуется соответствующий конструктор копирования). Как вы указали, исходный ServerSocket выйдет из области видимости, что больше не является проблемой, поскольку копия все еще действительна.
Если это не вариант для вас, используйте версию, указанную Рогилем (и придерживайтесь ручек ресурсов, таких как уникальный и общий указатель, они значительно облегчат вашу жизнь, если вы привыкли к GC :-)).