2013-12-19 4 views
0

Я прихожу из 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.

Если вам нужно больше кода, дайте мне знать.

+2

Я не вижу, где вы на самом деле * создаете * * new_sock. Кроме того, позаботьтесь о балансе 'new' с' delete'. – Bathsheba

+0

Да - создайте сокет с новым. Вы можете удалить его, когда вы в конце концов закроете его в ClientConnectionThread. –

+0

Каждый 'новый' нуждается в' delete', иначе он будет одинок. –

ответ

1

Ваш первый код не работает именно из-за того, что вы сказали. Объект выделяется в стеке, но как только он покидает область видимости, он уничтожается и, как следствие, закрывается указатель на сокет.

Если вы хотите сохранить объект «живым», вам нужно использовать указатели. Вы получили это право, но пропустили важный момент: вы до выделите объект! Для этого необходимо использовать оператор new как следующее:

ServerSocket *new_sock = new ServerSocket; 

Теперь вот загвоздка, на Java ваш объект будет освобождён автоматически с помощью газовой хроматографии, но C++ не имеет сборщика мусора, так что вам нужно сделать, это рукой. Как только вы закончите использовать объект, вам понадобится delete.

delete new_sock; 

Это может быть очень сложно, может вызвать много сбоев и даже утечек памяти. Если вы хотите некоторое поведение больше как GC Java, вы можете использовать shared_ptr, который будет автоматически освобождает объект (это не так просто, но вы легко найдете больше о том, что на Google.)

std::shared_ptr<ServerSocket> new_sock = std::shared_ptr<ServerSocket>(new ServerSocket); 
server.accept(*new_sock); 

(предполагается, что вы компилируются на C++ 11)

+0

Спасибо за объяснение, получил его работу. Как shared_ptr знает, когда автоматически освобождать объект? Когда ссылки на него = 0? – user2997491

+0

Meh - просто удалите его в конце клиентского потока <> сервера. Улов на внешнем уровне должен гарантировать, что исключения не покидают поток без разрушения сокета в первую очередь. –

+0

Да. Как правило, он создает несколько shared_ptr, каждый новый экземпляр добавляет 1 к счетчику, как только shared_ptr будет уничтожен, он уменьшает 1 из счета. Когда счетчик достигнет 0, последний shared_ptr удаляет объект. Также обратите внимание, что shared_ptr не является реальным указателем, он просто эмулирует один, сам shared_ptr статически распределяется. –

1

Вы можете сделать свою первую версию работы, если вы передадите копию вместо ссылки ServerSocket на свой поток (если это возможно - для серверного сокета понадобится подходящий конструктор копирования для этого). Исходный серверный сервер вышел бы из области действия, как вы указали, что теперь уже не проблема, поскольку копия все еще действительна.

Если вы не согласны с версией, которую указал Rogiel (и придерживаться ручек ресурсов, таких как уникальный и общий указатель, это значительно упростит вашу жизнь, если вы привыкли к GC :-)).

+0

Это очень полезно. Спасибо. – user2997491

Смежные вопросы