wxSocket: Warten bei 100% CPU Last



  • Hallo,

    hab ich da was falsch gemacht?

    Immer wenn eine Funktion wartet (z. B. auf Datenempfang),
    dann steigt die CPU-Last auf 100%.

    Mit Winsockets kann man doch auch warten, ohne dass ma alles verbruzzelt.

    Beispiel: (im Eventhandler vom Server bei anliegenden Daten eines Clients)

    // Sobald nix mehr zum Lesen vorhanden ist,
    	// wartet WaitForRead() 10 Sekunden bei 100% CPU Last
    	while (sock->WaitForRead(10) == true)
    	{
    	sock->Read(buffer, 255);
    	wxUint32 bytes = sock->LastCount();
    
    	buffer[bytes] = '\0';
    	received.append(buffer);
    	}
    

    Natürlich kann man ein "Protokoll" vereinbaren und z. B. ein
    Terminierungszeichen senden und dann die whileschleife abbrechen,
    bevor sie in den Timeout läuft.
    Aber wird man dadurch nicht anfällig für DOS-Attacken:
    Jemand verbindet sich zum Server, sendet ein paar Bytes ohne Terminator
    immer und immer wieder.
    Folge: CPU ist immer bei 100%

    mfg
    Martin


  • Mod

    wenns dein Hauptthread ist: wxSleep,
    ansonsten wxThread::Sleep.

    Hm, aber die Funktion die du aufrufst, blockiert.
    http://www.wxwidgets.org/manuals/2.6.2/wx_wxsocketbase.html#wxsocketbasewaitforread
    Musst du wohl anders machen.



  • Die Funktion darf ja gerne blockieren.
    Solange dabei die CPU-Last nicht auf 100% klettert.

    Winsockets haben da ein "select()".
    Das blockiert auch, aber halt ohne dass dabei Rechenleistung verbraucht wird.

    Schlafen gefällt mir jetzt nicht so gut, weil das wartet IMMER z. B. 10 Sekunden,
    auch wenn nach 2 schon Daten vorhanden sind.

    Ehrlich gesagt wüsst ich grad nicht, wie ich's anders machen sollte...

    trotzdem danke
    Martin


  • Mod

    Warum nimmst du nicht eine Event basierte Lösung ?
    http://wxforum.shadonet.com/viewtopic.php?t=4823



  • ist schon event-basiert:

    Es sollen alle anstehenden Daten eingelesen werden,
    und im Zweifel soll eine bestimmte Zeit lang darauf gewartet werden (hier: 10 Sekunden)

    void myDialog::onSocketEvent(wxSocketEvent & Event)
    {
    wxSocketBase *sock = Event.GetSocket();
    
    	switch(Event.GetSocketEvent())
    	{
    		case wxSOCKET_INPUT:
    		{
    		// We disable input events, so that the test doesn't trigger
    		// wxSocketEvent again.
    		sock->SetNotify(wxSOCKET_LOST_FLAG);
    
    		sock->SetTimeout(2);
    		sock->SetFlags(wxSOCKET_NOWAIT);
    
    		wxString received;
    
    		char * buffer = new char[3];
    
    			while (sock->WaitForRead(10) == true)
    			{
    			sock->Read(buffer, 2);
    			wxUint32 bytes = sock->LastCount();
    
    			buffer[bytes] = '\0';
    			received.append(buffer);
    			}
    
    		delete[] buffer;
    
    			if (received.length() > 0)
    			{
    			wxMessageBox(received);
    
    				if (sock->WaitForWrite(5) == true)
    				{sock->Write(received.c_str(), received.length());}
    				else
    				{wxMessageBox("timeout; nix gesendet");}
    
    			}
    			else
    			{wxMessageBox("nix empfangen");}
    
    		// Enable input events again.
    		sock->SetNotify(wxSOCKET_LOST_FLAG | wxSOCKET_INPUT_FLAG);
    
    		}break;
    
    		case wxSOCKET_LOST:
    		{
    		//wxMessageBox("client lost");
    		m_numClients--;
    		sock->Destroy();
    		}break;
    
    		default:
    		{
    
    		}break;
    	}
    }
    

    Wie oben beschrieben, verursacht WaitForRead() volle CPU Last

    alternativer case wxSOCKET_INPUT:
    jetzt verursacht Read() die 100%ige Prozessorauslastung (bis der Timeout abgelaufen ist)
    Das passiert immer dann, wenn Read() alles, was ansteht ausliest, d. h. wenn nach dem Read der "Eingabepuffer" leer ist, dann hängts

    case wxSOCKET_INPUT:
    		{
    		// We disable input events, so that the test doesn't trigger
    		// wxSocketEvent again.
    		sock->SetNotify(wxSOCKET_LOST_FLAG);
    
    		sock->SetFlags(wxSOCKET_WAITALL);
    		sock->SetTimeout(10);
    
    		char * buffer = new char[11];
    		sock->Read(buffer, 10); ///// <-------------------- hier 100% CPU
    		wxUint32 bytes = sock->LastCount();
    
    		buffer[bytes] = '\0';
    
    		wxMessageBox(buffer);
    
    			if (sock->WaitForWrite(5) == true)
    			{sock->Write(buffer, bytes);}
    			else
    			{wxMessageBox("timeout; nix gesendet");}
    
    		delete[] buffer;
    
    		// Enable input events again.
    		sock->SetNotify(wxSOCKET_LOST_FLAG | wxSOCKET_INPUT_FLAG);
    		}
    

Anmelden zum Antworten