2016-05-03 4 views
3

So habe ich diese winsock Anwendung (ein Server, mehrere Clients akzeptieren), wo im Haupt-Thread ich den Socket einrichten und erstellen Sie einen anderen Thread, wo ich für Clients (listen_for_clients Funktion).Übergabe von Daten an einen anderen Thread in einer C++ Winsock App

Ich bekomme auch ständig Daten von einem Gerät im Haupt-Thread, die ich anschließend zu Char-Arrays (Puffer) von Client Objekte verketten (BroadcastSample Funktion). Zur Zeit erstelle ich einen Thread für jeden verbundenen Client (ProcessClient Funktion), wo ich ein Client Objekt initialisiere und es zu einem globalen Vektor von Clients verschiebe, nach dem ich Daten an diesen Client über den Socket immer dann senden, wenn der Puffer im entsprechenden Client Objekt 4000 überschreitet Figuren.

Gibt es eine Möglichkeit, kann ich Daten aus dem Haupt-Thread zu den separaten Client-Threads senden, so brauche ich nicht Strukturen/Klassen (auch ein grünes Licht senden, wenn ich die bereits gesammelten Daten senden möchte) und Auch wenn ich einen globalen Container mit Objekten verwalte, was ist ein guter Weg, um ein getrenntes Client-Objekt daraus zu entfernen, ohne das Programm zu stürzen, weil ein anderer Thread den gleichen Container verwendet?

struct Client{ 
    int buffer_len; 
    char current_buffer[5000]; 
    SOCKET s; 
}; 

std::vector<Client*> clientBuffers; 

DWORD WINAPI listen_for_clients(LPVOID Param) 
{ 
    SOCKET client; 
    sockaddr_in from; 
    int fromlen = sizeof(from); 
    char buf[100]; 
    while(true) 
    { 
     client = accept(ListenSocket,(struct sockaddr*)&from,&fromlen); 
     if(client != INVALID_SOCKET) 
     { 
      printf("Client connected\n"); 
      unsigned dwThreadId; 
      HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &ProcessClient, (void*)client, 0, &dwThreadId); 
     } 
    } 

    closesocket(ListenSocket); 
    WSACleanup(); 
    ExitThread(0); 
} 

unsigned __stdcall ProcessClient(void *data) 
{ 
    SOCKET ClientSocket = (SOCKET)data; 
    Client * a = new Client(); 
    a->current_buffer[0] = '\0'; 
    a->buffer_len = 0; 
    a->s = ClientSocket; 
    clientBuffers.push_back(a); 

    char szBuffer[255]; 

    while(true) 
    { 
     if(a->buffer_len > 4000) 
     { 
      send(ClientSocket,a->current_buffer,sizeof(a->current_buffer),0); 
      memset(a->current_buffer,0,5000); 
      a->buffer_len = 0; 
      a->current_buffer[0] = '\0'; 
     } 
    } 
    exit(1); 
} 

//function below is called only in main thread, about every 100ms 
void BroadcastSample(Sample s) 
{ 
    for(std::vector<Client*>::iterator it = clientBuffers.begin(); it != clientBuffers.end(); it++) 
    { 
     strcat((*it)->current_buffer,s.to_string); 
     (*it)->buffer_len += strlen(s.to_string); 
    } 
} 
+0

Was machen die per-socked-Fäden für Sie? dauert der Aufruf 'send (socked, buffer, size, 0)' lange? Ich glaube nicht, dass du etwas gewinnst, wenn du diese Threads hast. – Jfevold

+0

@Jfevold: als allgemeine Regel, wenn Sie mehrere Clients haben alle I/O sollte entweder in separaten Threads oder asynchron erfolgen. Sonst könnte ein einzelner missgebildeter Klient möglicherweise alles zum Schreien bringen. –

+0

Wenn Sie eine ausreichend aktuelle Version von C++ verwenden, sollten Sie wahrscheinlich die Threading-Unterstützung verwenden, die ohne Zweifel Thread-sichere Warteschlangen und ähnliches enthält. Wenn Sie die Windows-API verwenden möchten, kann [verknüpfte einfach verknüpfte Listen] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms684121 (v = vs.85) .aspx) möglicherweise eine sein geeignete Option. –

Antwort

1

This link hat einige Microsoft-Dokumentation zu MS-Stil mutexes (muticies?).

This other link hat einige allgemeine Informationen über Mutexe.

Mutexe sind der allgemeine Mechanismus zum Schutz von Daten, auf die mehrere Threads zugreifen. Es gibt Datenstrukturen mit integrierter Thread-Sicherheit, aber nach meiner Erfahrung haben sie normalerweise Vorbehalte, die Sie schließlich übersehen werden. Das sind nur meine zwei Cent.

Auch für den Datensatz sollten Sie nicht strcat, sondern strncat verwenden. Wenn einer Ihrer Clientservicing-Threads auf einen dieser Puffer zugreift, nachdem strncat den alten '\0' überschrieben hat, aber bevor er den neuen angehängt hat, haben Sie einen Pufferüberblick (lesen Sie das letzte Ende des zugewiesenen Puffers).

Mutexes löst auch Ihr aktuelles busy-waiting Problem. Ich bin derzeit nicht in der Nähe eines Windows-Compilers, oder ich würde versuchen, mehr zu helfen.

Verwandte Themen