В настоящее время я разрабатываю TCP-сервер и использую многопоточность, поэтому для этого я инициализирую сервер с помощью Server.start(), который дает мне fd лайк, а затем я запускаю бесконечный цикл, чтобы принять и запустить новый поток, например:
int main()
{
spdlog::set_pattern("[%H:%M:%S %z] [%^---%L---%$] [thread %t] %v");
Server server(9001);
int sockfd = server.start();
if (sockfd < 0)
{
spdlog::error("Cannot init server");
return 1;
}
while (true)
{
int fd = server.loop();
std::thread t(newclient, fd);
}
}
void newclient(int fd)
{
Handler handler;
handler.loop(fd);
closesocket(fd);
};
обработчик.цикл:
void Handler::loop(int fd){
std::string buffer;
Communication communication(fd);
while(true){
buffer.erase();
buffer = communication.recv_str();
if (buffer == "") {
continue;
}
}
...
}
и communication.recv_str():
std::string Communication::recv_str(){
std::vector<char> buffer(CHUNK_SIZE);
std::string rcv;
long bytes_received = 0;
do {
bytes_received = recv(fd, &buffer[0], CHUNK_SIZE, 0);
if ( bytes_received < 0 ) {
std::cout << "recv failed, err: " << WSAGetLastError() << std::endl;
} else if ( bytes_received == 0 ) {
return "";
} else {
rcv.append(buffer.cbegin(), buffer.cend());
}
} while( bytes_received == CHUNK_SIZE );
return rcv;
}
поэтому, если я скомпилирую и запущу это при попытке подключения к серверу, я получу следующее сообщение:
Но по причине, которую я не могу объяснить, происходит сбой на recv, я пытался отладить это, но не могу объяснить эту вещь. Никаких ошибок в сообщениях или других указаний я не понимаю.
PS: отправка работает отлично.
вылетает при приеме" - что вы имеете в виду под "вылетом"? Возвращает ошибку (какую?), приложения закрываются (т.е. сбой памяти),... Пока нет ничего очевидного, что могло бы вызвать сбой. Однако есть проблема: вы предполагаете, что если bytes_received не CHUNK_SIZE, то данных больше не будет. recv будет читать только до заданного размера, но не гарантирует, что прочитает все, даже если узел отправит больше данных.
Ваш объект std::thread выходит за пределы области видимости до завершения потока. Вам нужно поместить объект std::thread в более постоянное место.





Если объект std::thread разрушен, а связанный с ним поток все еще работает, вызывается std::terminate.
Это указано в документации:
Если
*thisимеет связанный поток (joinable() == true), вызываетсяstd::terminate().
В этой части вашего кода:
while (true)
{
int fd = server.loop();
std::thread t(newclient, fd);
}
Область действия t заканчивается в конце текущей итерации, и объект std::thread уничтожается, хотя он, скорее всего, еще работает. Поэтому вызывается std::terminate и программа завершает работу.
Чтобы решить эту проблему, вам следует хранить все объекты std::thread до тех пор, пока работает связанный с ними поток. Вы можете, например, хранить их в контейнере в своем классе Server.
Слишком мало контекста, чтобы помочь вам. Пожалуйста, попробуйте создать минимальный воспроизводимый пример и показать нам.