簡體   English   中英

客戶端斷開連接后,服務器應用程序崩潰

[英]Server application crashing as soon as a client disconnects

因此,我只是使用winsock2和TCP編寫了一個簡單的多線程客戶端服務器應用程序。

以下是其工作原理的快速摘要:

服務器主線程處於無限循環中,接受客戶端,然后還將它們添加到服務器向量中,該向量包含每個連接的客戶端,如下所示:(僅添加我要提問的重要內容)

std::vector <Client*> clients;
while (true){
    clients.push_back(&Client(accept(serverSocket, NULL, NULL), this));
}

當新客戶端連接到服務器時,我們基本上以新客戶端的套接字和服務器本身為參數創建一個新的客戶端對象。

然后,我的想法是為每個客戶端提供自己的線程,以便每個客戶端可以同時發送數據。

std::thread tickThread;

Client::Client(SOCKET socket,Server* server) :
isConnected(true),
socket(socket),
server(server)
{
    tickThread = std::thread(&Client::tick,this);
}

然后,客戶端線程檢查客戶端是否發送了某些東西,然后將其發送到服務器。 它還檢查客戶端是否仍然連接。 無效的Client :: tick(){

while (isConnected){
    errorHandler = recv(socket, receivedData, 255, 0);
    if (errorHandler == SOCKET_ERROR){
        disconnect();
    }
    else {
        //send received data to server
    }
}

如果客戶端斷開連接,它將告訴服務器從連接的客戶端向量中刪除客戶端,然后將“ isConnected”布爾值設置為false,以便線程可以退出其功能。

void Client::disconnect(){
    isConnected = false;
    server->removeClient(this);
}

這就是它應該如何工作的方式,但是,一旦客戶端再次斷開連接,服務器就會崩潰並顯示以下錯誤:

R6010-已調用abort()

所有調試都向我顯示這是我的錯誤:

switch (_CrtDbgReportW(_CRT_ERROR, NULL, 0, NULL, L"%s", error_text)){
          case 1: _CrtDbgBreak(); msgshown = 1; break;
          case 0: msgshown = 1; break;
}

所以,是的,我真的不知道是什么原因導致此崩潰,但是我懷疑它可能與使用客戶端功能的線程相關,該功能基本上已被刪除,因為正在從服務器的客戶端向量中將其刪除。

假如這是問題所在,你們能給我一些更好的方法來實現每個擁有自己線程的客戶端的想法嗎?

編輯:更改了向量錯誤,但是當客戶端斷開連接后,崩潰仍然會發生

錯誤在以下代碼塊中:

while (true){
    clients.push_back(&Client(accept(serverSocket, NULL, NULL), this));
}

Client(accept(serverSocket, NULL, NULL), this)是一個生成臨時Client對象的表達式,該對象在語句完成執行Client(accept(serverSocket, NULL, NULL), this)被銷毀。 但是,您需要獲取該臨時對象的地址並將其添加到vector

如果要創建Client對象並存儲指向它們的指針,則需要為其分配內存。 我建議使用std::unique_ptr來管理它們,以便您的vector聲明對它們的內存的所有權,如果將它們從vector中刪除或vector本身被破壞,它們會自動釋放它們。 然后您的代碼變為:

std::vector<std::unique_ptr<Client>> clients;
while (true){
    clients.push_back(std::make_unique<Client>(accept(serverSocket, NULL, NULL), this));
}

在這段代碼中:

clients.push_back(&Client(accept(serverSocket, NULL, NULL), this));

您正在將臨時對象的地址推入容器。 當push_back()完成后,臨時對象將被銷毀,因此該地址不再有效。 我想知道,哪種編譯器可以執行此操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM