2016-06-03 8 views
2

Ich schreibe Multithreading-Server mit CSocket. Wie üblich habe ich den Server-Socket und muss für jeden verbundenen Client einen Empfangs-Socket erstellen. Um mehrere Clients zu behandeln, möchte ich für jeden Client std::thread neu erstellen, detach es, und als nächstes diesen Client innerhalb Thread-Funktion behandeln.Übergabe von CSocket zu Std :: Thread


Ich versuche, wie dies zu tun:

int client_handler(CSocket receiver) 
{ 
    return 1; 
} 

CSocket server; 
BOOL created = server.Create(12345); 
server.Listen(); 
while(true) 
{ 
    CSocket receiver; 
    if (server.Accept(receiver)) 
    { 
    std::thread handler(client_handler, receiver); 
    } 

} 
... 

ich std::thread Instanziierung einen Compiler-Fehler bekam:

error C2664: 'std::tuple<int (__cdecl *)(CSocket),CSocket>::tuple(std::tuple<int (__cdecl *)(CSocket),CSocket> &&)': cannot convert argument 1 from 'int (__cdecl &)(CSocket)' to 'std::allocator_arg_t' 

ich std::thread docs gelesen habe, aber noch können‘ t verstehen - warum kann СSocket nicht weitergegeben werden?

+0

MSDN ist überraschend leise auf Kopie-Konstruierbarkeit von 'CSocket'. Kann es sein, dass es einfach nicht kopierbar ist? – SergeyA

+0

@SergeyA 'CSocket' wird von' CObject' abgeleitet, das tatsächlich nicht kopierbar ist. Es ist wahrscheinlich am besten "Detach" zu machen, rohe 'SOCKET' an den Thread zu übergeben und' Attach' dort anzubringen. –

+0

@IgorTandetnik, und ich nehme an, es ist auch nicht beweglich? – SergeyA

Antwort

0

Problem:

Sie verwenden ein CSocket Objekt im Thread Instanziierung, es durch Wert übergeben. Die Argumente für das auf std::thread übertragene abrufbare Wort sind beweglich oder kopierbar. Leider ist ein CSocket weder kopierbar noch versetzbar, deshalb erhalten Sie den Fehler.

Lösung:

Die Alternative wäre es, die Buchse durch Bezugnahme passieren. In diesem Fall müssten Sie es mit std::ref() umhüllen, um zu vermeiden, dass Ihr Thread einen Verweis auf eine Kopie erhält. Aber Sie können diese Alternative hier nicht berücksichtigen, weil receiver ein Objekt mit lokalem Speicher ist. Es kann zerstört werden, bevor der Thread beendet ist, was zu undefiniertem Verhalten führt.

Zwei Möglichkeiten dann:

  1. haben receiver als Mitglied der Klasse, oder zumindest dafür sorgen, dass es bis der Faden vorhanden ist beendet. Der Referenzansatz würde dann lebensfähig werden
  2. erstellen Sie die CSocket dynamisch, mit einer shared_ptr und übergibt diese shared_ptr in der Thread-Instantiierung (und in der client_handler()).

Kommentare:

Während Ihrer aktuellen Ausgabe nicht unbedingt im Zusammenhang beachten Sie, dass in Ihrem Snippet Sie handler als lokales Objekt zum if -bloc erstellen. Das Objekt wird also zerstört, wenn Sie den Block verlassen und sich nicht dem Thread angeschlossen haben. Dies wird UB verursachen: Sie müssen den Thread verbinden oder trennen, bevor Sie das entsprechende Thread-Objekt löschen.

So ändern Sie entweder die Struktur Ihres Codes, um diese Einschränkung zu berücksichtigen, und verwalten Sie die Threads, oder Sie verwenden std::async(), falls Sie den Empfangscode nur asynchron ausführen möchten.

Verwandte Themen