Spezialisten gefragt: Windows Socket: Empfangsschleife verschluckt Daten.



  • sinnlos.



  • Mondmann schrieb:

    Wenn irgendwas anders ist, dann bekomme ich zB.1452 geliefert und das nächstemal 2643. Und DAS sind dann meine nullen. Es ist einfach der Rest vom letzten Packet!.

    Genau. Deswegen hatte ich anfangs gemeint lies die Doku zu send/recv nochmal, denn da steht das eigentlich drinnen 🙂

    Diese zwei Werte kommen übrigens recht häufig vor...warum weiß ich auch nicht.

    Das liegt an der MTU, also der max. Paketgrösse des verwendeten Netzwerks. Die ist bei Ethernet normalerweise 1500. Die 1452 sind wahrscheinlich das was übrigbleibt wenn man die ganzen Headers wegrechnet.

    Also was fange ich nun damit an?
    Ich prüfe einfach den Rückgabewert von recv.
    Sind es 4095 weiß ich, daß ein Paket komplett ist.
    Sind es weniger, zähle ich einfach zusammen bis ich 4095 zusammen habe.
    Dann ist dieses Paket komplett.

    Das wäre mal ein erster Schritt, was meint Ihr?

    Das wäre eine Möglichkeit, ja. Oder eben du überträgst gleich die Länge der Nutzdaten vor dem Paket - das wäre effizienter (weniger Nulldaten die du rumsendest).



  • Mondmann schrieb:

    Leider gehen doch Pakete verloren.

    Du meinst auch nicht Pakete sondern Bytes, denn wie erwähnt gehen TCP-Pakete nicht verloren. Und da keine TCP-Pakete abhanden kommen, kommen auch keine Bytes abhanden. Also ist immer noch nen Fehler in deiner Anwendung 😉



  • ist bestimmt ein Fehler in der TCP/IP Implementierung des Betriebssystem



  • bist du sicher? oder vielleicht doch ein compiler fehler...



  • Es kann eigentlich nur ein Fehler des OS sein. Ist halt Windows! Da braucht man sich nicht zu wundern.
    Oder der *Microsoft* Compiler macht mal wieder Fehler! Was ja eigentlich alle paar Minuten vorkommt!



  • Ich habe mal gebastelt und mit dem unten angeführten Code gehts ganz gut.
    Man sieht die Schleife für 1. Paket. Diese Schleife ist nochmal in eine For-Schleife verpackt die die anzahl der empfangenen Pakete mitzählt und auswertet.Dises ist hier nicht abgebildet.

    iGesLen und iSollLen werden nach jedem Durchlaf neu initialisiert.

    iGesLen = 0;
    iSollLen = MAX_REC_BUF;
    iFehlerCnt = 0;
    
    	while(iGesLen < MAX_REC_BUF )
    	{
    		if( strstr(pRecv,STOPSEQUENZ) !=0)
    		{	
    			break;
    		}
    
    		if((iAktLen = recv (s,pRecv, iSollLen,0 )) > 0)
    		{	
    			memcpy(InBuffer + iGesLen,pRecv,iAktLen);
    			iGesLen += iAktLen;
    			iSollLen -= iAktLen;			
    		}
    		else
    		{
    			if( strstr(pRecv,STOPSEQUENZ) !=0)
    			{
    				break;
    			}
    
    			iFehlerCnt++;
    			Sleep(10);
    		}
    		if(iFehlerCnt >= 100)
    		{
    			break;
    		}
    	}
    

    Meine Denkfehler bzw. Unwissenheit waren:
    1. daß recv immer das empfängt was send() sendet und
    2. ging es über meine Vorstellung hinaus, daß man recv auch mal weniger empfangen lassen kann als der max. buffer.
    3. daß Pakete verloren gehen, dem ist nicht so.
    4. Daß strlen bzw. strcpy ja nur bis zum \0 auslesen und selbst wenn danach noch Daten stehen diese nicht mitgezählt/kopiert werden.
    Was in diesem Falle ja durchaus öfters der Fall sein wird.

    Ich Danke allen die sich Mühe gemacht haben und mir geduldig erklärt und geantwortet haben.
    Es ist ein tollen Forum und ich werde hier immer gut geholfen, auch wenns meinem festgefahreren Hirn mal schwieriger wird.

    Allerdings habe ich nie bezweifelt, daß der Fehler an mir liegt.
    Mondmann



  • Zur Info: Ich habe mich bei meinem letzten Satz verschrieben...jetzt stimmts was ich sagen wollte....:-)



  • Bei einem Fehler würde ich sofort abbrechen, der Socket wird sich nicht wieder "erholen" (glaub mir, ich hab nen Server geschrieben mit dem sich täglich 1000e Geräte verbinden und der pro Tag etliche GB an Daten verschickt).

    Und was das strstr in der Schleife soll verstehe ich nicht ganz.
    Kannst du denn sicherstellen dass STOPSEQUENZ *niemals* mitten in einem Paket vorkommen kann?



  • Hallo hustbaer.

    STOPSEQ wird niemals mitten im stream vorkommen, außer es geht etwas schief und es steht noch ein "Rest" im Socket.
    Es ist einfach das Ende der Sendung und da breche ich ab, sonst blockiert recv.

    Ja bei einem Fehler..hmm...ich denke das ist noch ein Problemchen.
    Wenn jetzt ein Fehler vorkommt, der Socket aber noch nicht leer ist und ich breche ab..was dann?

    Dann holt recv bei der nächsten Anfrage auf diesem Sochet erstmal den Rest ab mit dem ich dann nichts anfangen kann.
    Also was hilft?
    Socket beenden und neu aufbauen?



  • Wenn recv einen Fehler meldet machst du den Socket zu, da die Verbindung dann wahrscheinlich bereits "tot" ist. Der Fehlercode (den du mit WSAGetLastError bekommst) sagt dir warum ("connection reset by peer" etc.).

    Ausnahmen sind natürlich Fehler wie WSAEWOULDBLOCK (bekommst du bei blocking IO nicht), WSAEMSGSIZE (bekommst du bei TCP nicht), WSAESHUTDOWN (bekommst du nur wenn du shutdown aufgerufen hast - was du dann wissen müsstest) etc.

    Alles in Allem kann man sagen: wenn du bei blocking IO einen Fehler bekommst dann hat entweder dein Programm einen Fehler gemacht, oder die Verbindung ist "tot", oder du tust etwas "spezielles" (z.B. shutdown aufrufen oder einen blocking Socket aus mehreren Threads gleichzeitig zu verwenden etc.), wobei du dann aber wissen müsstest was du da tust, und welche Fehler es bei send/recv zur Folge haben kann.

    Wenn du unsicher bist lies dir einfach die Liste der möglichen Fehlercodes in der MSDN durch (Funktionen recv und send). Und schreib einen Eintrag in ein Logfile wenn send oder recv einen Fehler zurückliefert, dann kannst du zumindest gucken was passiert.



  • @hustbaer

    Wenn ich 4095Bytes durchs Netz schicke, wird dieses Paket auf jeden Fall fragementiert, da der MTU ja standesgemäß 1500 ist, oder?



  • Wenn ich 4095Bytes durchs Netz schicke, wird dieses Paket auf jeden Fall fragementiert, da der MTU ja standesgemäß 1500 ist, oder?

    Jep. Warum ist das wichtig für dich?



  • Nur so, interessehalber, ob dadurch die Kommunikation verlangsamt wird...
    Danke.

    Mondmann



  • Ich glaube man nennt es in dem Fall nicht fragmentieren, aber ja, es werden mehrere Pakete verschickt.

    Kann dir bei TCP aber eigentlich egal sein. Ein grosses Paket braucht auch länger als ein kleines, von daher kann es eigentlich egal sein wie gross ein Paket werden darf -- Platz sparen bringt immer was.


Anmelden zum Antworten