Это - с чисто точки зрения решения проблем - решаемая проблема, но базовый механизм может быть интересен некоторым, включая меня.
Я написал довольно простой сервер, прослушивающий данный порт TCP,Я написал это таким образом, чтобы он мог принимать несколько запросов, а не только один, и завершать работу с циклом while
.
Поскольку у меня нет опыта работы с C ++, я нашел решение в Google и сфабриковал егомои потребности. Часть кода, о которой идет речь, выглядит следующим образом:
socklen_t addrlen = sizeof(address);
while(true) {
try {
std::cerr << "Listening..." << std::endl;
if(listen(socketId, 3) < 0) {
std::cerr << "Error while listening for incoming connections" << std::endl;
throw;
}
processRequest(accept(socketId, (struct sockaddr *) &address, &addrlen));
} catch(Json::RuntimeError& e) {
std::cerr << "Json error: " << e.what() << std::endl;
} catch(...) {
std::cerr << "Unknown error" << std::endl;
throw;
}
}
Проблема с этим кодом сложна и может быть очевидна для более опытных из вас, но она определенно не очевидна для меня.
Я покажу вам часть определения класса:
int socketId;
sockaddr_in address;
const RequestProcessor& processor;
Обратите внимание на порядок этих переменных.
Используя метод выше и переменные в этом порядке, первыйзапрос выполняется гладко, и программное обеспечение начинает прослушивать следующий запрос, как и предполагалось.
Однако, когда приходит второй запрос, ссылка processor
перезаписывается, предположительно, из-за некоторого переполнения памяти - или чего-то другогоnamed - происходящее, которое перезаписывает ячейку памяти, на которую указывает эталон processor
, вызывая ошибку где-то вниз по линии в методе, не показанном здесь.
Решение простое, но найти его действительно сложно. :
while(true) {
try {
std::cerr << "Listening..." << std::endl;
if(listen(socketId, 3) < 0) {
std::cerr << "Error while listening for incoming connections" << std::endl;
throw;
}
socklen_t addrlen = sizeof(address);
processRequest(accept(socketId, (struct sockaddr *) &address, &addrlen));
} catch(Json::RuntimeError& e) {
std::cerr << "Json error: " << e.what() << std::endl;
} catch(...) {
std::cerr << "Unknown error" << std::endl;
throw;
}
}
Все, что я сделал, это заменил место создания переменной addrlen
. Это решает проблему и дает дополнительное преимущество, так как является более «разумным».
Вопрос в том, почему перемещение инициализации addrlen
решает эту проблему?