recv Funktion Problem



  • if(ret == -1)
        {
            buf[ret] = '\0';
            break;
        }
    

    Müsste eigentlich heißen:

    if(ret == -1)
        break;
    
    buf[ret] = 0; // statt '\0' geht auch einfach 0
    

    Und das cout muss in die Schleife.



  • Danke, jetzt krieg ich wenigstens was auf die Console ausgegeben 😃 Aber die Schleife wird komischerweise einfach nicht verlassen, nach 5 Sekunden verschwindet alles und es sieht so aus als ob recv irgendwie "leeres" weiter empfängt...

    std::string szSendData = "GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n\0";
    	int bytesSent = 0;
    	do
    	{
    		int result = send(ConnectSocket, szSendData.c_str() + bytesSent, szSendData.size() - bytesSent, 0);
    		bytesSent += result;
    	} while(bytesSent < szSendData.size());
    
    	char buf[256];
    	while(1)
    	{
    		int ret = recv(ConnectSocket, buf, sizeof(buf) - 1, 0);
    		if(ret == -1)
    			break;
    
    		buf[ret] = 0;
    		cout << buf << endl;
    	}
    
    	system("PAUSE");
    

    So sieht es bis jetzt aus, doch zur Pause komm ich einfach nicht. 😕



  • recv liefert im Falle einer erfolgreich geschlossenen Verbindung (also wenn es nichts mehr zu lesen gibt) 0 zurück. -1 nur bei Fehlern.



  • if(ret <= 0)
    			break;
    

    Könnte klappen...



  • Ich kenn´ die Spezifikationen des HTTP Protokolls nicht, aber vielleicht darf der Server die Verbindung trennen, nachdem er eine Anfrage beantwortet hat. In diesem Fall wird result irgendwann 0. Diesen Fall behandelst du nicht, vielleicht liegt´s ja daran. Ansonsten kannst du dir result ja ausgeben lassen bzw. mit dem Debugger untersuchen, um festzustellen, wann nichts mehr empfangen wird.

    Edit:
    Lerneffekt: Browserfenster nach 1h ruhig mal aktualisieren, um zwischenzeitliche Postings zu lesen 😃



  • Es lag tatsächlich an der 0 als Rückgabewert. 😃
    Doch mein Problem liegt jetzt ganz wo anders, ich würde gerne senden & empfangen in einem bestimmten Abstand. Soweit so gut... Empfangen wird nur das erste Paket, danach geschieht nichts...

    std::string szSendData = "GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n\0"; 
    while(1)	
    {
    	int bytesSent = 0;
    	do
    	{
    		int result = send(ConnectSocket, szSendData.c_str() + bytesSent, szSendData.size() - bytesSent, 0);
    		bytesSent += result;
    	}while(bytesSent < (signed)szSendData.size());
    
    	std::stringstream EndBuf;
    	char buf[256];
    	while(1)
    	{
    		int ret = recv(ConnectSocket, szBuf, sizeof(szBuf) - 1, 0);
    		if(ret == 0)
    			break;
    
    		buf[ret] = 0;
    		EndBuf << buf;
    	}
    	std::string Data = EndBuf.str();
    	cout << Data << endl;
    
    	Data.clear();
    	EndBuf.clear();
    	buf[0] = 0;
    	Sleep(6000);
    }
    


  • Ich hab jetzt nicht den ganzen Thread gelesen - aber die innere while-Schleife wird ja nur verlassen, wenn google die Verbindung schließt. Tut es aber nicht, sondern wartet auf neue Anfragen.
    Bei HTTP schließen idR auch die Clients die Verbindung.

    Du solltest dir vielleicht mal boost::asio anschauen. Ich fande es auch erst erschreckend, sobald man das Prinzip einmal im Kopf hat ist es aber easy.

    Ansonsten kannst du nach jedem erfolgreichen recv-Aufruf schauen, ob das angekommene Paket soweit fertig ist. Das erkennst du an einem vorkommenden "\r\n\r\n" im Text. Wenn die Antwort von Google also vollständig ist, wäre das evtl auch ein "guter" Punkt, die Schleife zu verlassen.



  • Oder einfach Connection: close senden.



  • Genau, warum eine gute Lösung nehmen, wenn es auch einen dämlichen Workaround gibt.. PlanloserCoder will doch offensichtlich jedes Paket nach Empfang ausgeben und eine neue Anfrage senden.

    Übrigens ist das \0 am Ende vom zu sendenden String Unsinn, die wird laut Protokoll nicht mitgeschickt (abgesehen davon, dass sie eh schon am String hintendran hängt, bei .size() aber nicht berücksichtigt wird).

    Und die Rückgabewerte von send und recv sollten immer noch auf -1 getestet werden.



  • Dämlicher Workaround? Das ist 100 mal besser als irgendwelchen komplizierten Code zu schreiben, den niemand lesen kann.



  • Danke für den Vorschlag mit boost::asio, werde mich in meinem nächsten Projekt mal damit auseinandersetzen, jedoch hab ich jetzt schon die WinAPI genommen und mein "Projekt" ist eigentlich fertig, bis auf das, dass er nicht nochmal ein zweites mal empfängt, was sehr wichtig ist.
    An "Connection: close" habe ich garnicht drann gedacht, wohl möglich liegt es wohl doch darann. Habe immer gedacht das is an dem buffer liegt, deswegen hab ich ihn auch geleert am Ende der while Schleife. 🙄
    Muss ich irgendwas beachten wenn ich ein "Connection: close" sende nach dem ich die Daten ausgegeben habe? Denn so funktioniert es auch noch nicht...

    std::string szSendData = "GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n";
    while(1)   
    {
        int bytesSent = 0;
        do
        {
            int result = send(ConnectSocket, szSendData.c_str() + bytesSent, szSendData.size() - bytesSent, 0);
            bytesSent += result;
        }while(bytesSent < (signed)szSendData.size());
    
        std::stringstream EndBuf;
        char buf[256];
        while(1)
        {
            int ret = recv(ConnectSocket, Buf, sizeof(Buf) - 1, 0);
            if(ret == 0)
                break;
    
            buf[ret] = 0;
            EndBuf << buf;
        }
        std::string Data = EndBuf.str();
        cout << Data << endl;
    
        const char *close = "Connection: close\r\n\r\n";
        send(ConnectSocket, close, sizeof(close), 0);
    
        Data.clear();
        EndBuf.clear();
        buf[0] = 0;
        Sleep(6000);
    }
    

    Das ganze HTTP Zeugs scheint mir sehr komplex, damit hatte ich nicht gerechnet. :p



  • 314159265358979 schrieb:

    Dämlicher Workaround? Das ist 100 mal besser als irgendwelchen komplizierten Code zu schreiben, den niemand lesen kann.

    Sorry, ich war ein wenig harsch. Kann schon eine gute Lösung sein, allerdings muss der TO dann noch jedesmal neu verbinden.

    @PlanloserCoder:
    Variante 1, mit Connection: close:

    std::string szSendData = "GET / HTTP/1.1\r\nHost: www.google.com\r\nConnection: close\r\n\r\n";
    while(1)
    {
        // Senden
        int bytesSent = 0;
        do
        {
            int result = send(ConnectSocket, szSendData.c_str() + bytesSent, szSendData.size() - bytesSent, 0);
            bytesSent += result;
        }while(bytesSent < (signed)szSendData.size());
    
        // Empfangen
        std::stringstream EndBuf;
        while(1)
        {
            char buf[256];
            int ret = recv(ConnectSocket, Buf, sizeof(Buf) - 1, 0);
            if(ret == 0)
                break;
    
            buf[ret] = 0;
            EndBuf << buf;
        }
        cout << EndBuf.str() << endl;
    
        Sleep(6000);
    
        // TODO: Hier neu verbinden, ist ja geschlossen worden
    }
    

    Variante B, mit Paket-Ende herausfinden:

    std::string szSendData = "GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n";
    while(1)
    {
        // Senden
        int bytesSent = 0;
        do
        {
            int result = send(ConnectSocket, szSendData.c_str() + bytesSent, szSendData.size() - bytesSent, 0);
            bytesSent += result;
        }while(bytesSent < (signed)szSendData.size());
    
        // Empfangen
        std::stringstream EndBuf;
        while(1)
        {
            char buf[256];
            int ret = recv(ConnectSocket, Buf, sizeof(Buf) - 1, 0);
            if(ret == 0)
                break;
    
            buf[ret] = 0;
            EndBuf << buf;
    
            // Paket fertig?
            if ( EndBuf.str().find("\r\n\r\n") != std::string::npos )
                break;
        }
        cout << EndBuf.str() << endl;
    
        Sleep(6000);
    }
    

Anmelden zum Antworten