Winsock TCP optimierung bzw machung^^



  • aha un was soll ich machen?



  • wie waers, wenn du brauchbaren code postest und mal debugging-techniken lernst. ich kau dir das jetzt nicht vor. dafuer hast du zaehne, hoffe ich.



  • keks. send() sendet nicht immer genausoviel wie man übergibt, sondern bloss soviel wie die sockets implementierung gerade lust hat. steht in der doku. für recv gilt dasselbe. lies es nach 😉



  • Dieser Thread wurde von Moderator/in HumeSikkins aus dem Forum C++ in das Forum WinAPI verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • ausserdem nimmt man nicht &buf auf arrays. ein buch oder tutorial waere jetzt angebracht.



  • while(!source.eof())
    	{
    		source.read((char*)buf,1000);
    		send(s,buf,1000,0);
    	}
    	send(s,"finish",7,0);
    

    so sieht die sendroutine wirklich aus
    aber warum sendet es nur so viel wies lust hat bzw bei welscher doku hast du das? bei msdn? da hab ich das hier:

    This function is used to write outgoing data on a connected socket. For message-oriented sockets, care must be taken not to exceed the maximum packet size of the underlying provider, which can be obtained by using getsockopt (Windows Sockets) to retrieve the value of socket option SO_MAX_MSG_SIZE. If the data is too long to pass atomically through the underlying protocol, the error WSAEMSGSIZE is returned and no data is transmitted.

    das heisst es sendet garnix wenn die grösse überschritten wurde aber es wurde ja was gesendet also wurde die grösse auch nicht überschritten



  • wenn du einen SOCK_STREAM socket hast interessiert SO_MAX_MSG_SIZE nicht, und genau da liegt wahrscheinlich auch der knackpunkt der unverständlichkeit!

    welche art socket benutzt du ??

    bei sock_stream musst du dir vorstellen, du hast nen riesen stapel bytes, die schiebst du in den socket.
    der wirft die packete übers netzwerk wie er grad laune hat (kan sein das er alles schickt kann sein das er nur 1 byte schickt)

    bei SOCK_DGRAM
    wird erst ein paket geschnürt und dann komplett versendet (das ist aber UDP nicht TCP)
    damit das paket nicht zu groß wird, ist die größe des sendbaren array durch SO_MAX_MSG_SIZE (zu erhalten mittels getsocktoppt()) limitiert.

    [EDIT]

    wie rackwitz schon sagte

    ausserdem nimmt man nicht &buf auf arrays. ein buch oder tutorial waere jetzt angebracht.

    du übergibst dort die referenz auf den pointer deines array!!!
    da kann auch nichts sinnvolles bei rauskommen.

    "buf" ist bereits ein pointer über die [] kannst du aber das array hinter dem pointer indizieren *duckt sich weil er weis das das SO nicht astrein formuliert ist



  • Ähm noch was anderes: Es ist doch glaube ich nur so, dass die Bytes, welche durch einen Aufruf mit send verschickt werden in korrekter Reihenfolge ankommen. Es ist aber nicht garantiert, dass die Bytes welche durch mehrere send-Aufrufe verschickt werden, auch genau in der Reihenfolge der Aufrufe ankommen. Oder irre ich mich da jetzt? (Alles natürlich auf TCP Sockets bezogen)



  • das ist DEFINITIV NICHT so!
    dafür sind socket ja gerade da, damit JEDER send 100%ig in der richtigen reihenfolge ankommt!!!
    das einzige ungewisse ist die menge die in einem schub übertragen wird, ansonsten verhält sich der socket wie ein FIFO buffer.

    (ausgenommen du schreibst in mehreren threads auf einen socket und das wäre gelinde gesagt dumm _ ansonsten empfehle ich für die risikofreudigen CRITICAL_SECTION)



  • nep schrieb:

    Ähm noch was anderes: Es ist doch glaube ich nur so, dass die Bytes, welche durch einen Aufruf mit send verschickt werden in korrekter Reihenfolge ankommen. Es ist aber nicht garantiert, dass die Bytes welche durch mehrere send-Aufrufe verschickt werden, auch genau in der Reihenfolge der Aufrufe ankommen. Oder irre ich mich da jetzt? (Alles natürlich auf TCP Sockets bezogen)

    Du hast TCP geschrieben, und TCP impliziert nunmal nen stream socket (SOCK_STREAM). Bei stream sockets ist es eben so wie ich geschrieben habe, also dass send() nur soviel verschickt wie es gerade lustig ist, dafür ist allerdings 101% garantiert dass die Daten in der richtigen Reihenfolge am anderen Ende rauskommen.

    Bei nem datagram socket (SOCK_DGRAM, das wäre dann z.B. UDP statt TCP) ist es eben andersrum, d.h. entweder verschickt send() alles was man übergeben hat oder garnix, dafür ist NICHT garantiert dass irgendwas in der Reihenfolge ankommt wie es gesendet wurde.

    Du musst die Doku schon aufmerksam lesen, und nachlesen wenn da etwas steht wo dir nicht klar ist was es bedeutet bzw. ob es auf dein Programm zutrifft -- eben sowas wie "For message-oriented sockets" (was eben einen "datagram socket" beschreibt, und damit niemals auf TCP zutreffen kann).



  • also ich finde diese "methode" ein datei zu übertragen um es sanft aus zu drücken ... zum scheitern verurteilt ...

    ok ich sehe jetzt nicht wie du die verbindung initiallisierst, aber vermutlich genauso minimal^^

    ich hab schon viel mit vb6 un dateien gemacht ... was scheinbar grundlegend fehlt^

    zum thema warum kommen einige bytes (schätze mal gar pakete) nicht an ... TCP garantiert eine "fehlerfreie verbindung" (ist eigentlich quatsch) sie garantiert nur das kein fehler unbemerkt passiert, sowie das ein paket übermittelt wird(falls doch nicht ist da ein fehler) ... die reinfolge sollte eigentlich stimmen je grösser die strecke ist desto höher ist die wahrscheinlichkeit das pakete NICHT in der richtigen reihnfolge ankommen, was u.a. probleme mit VoIP verursacht ... es ist aber für datei transfer kein Problem.

    wer ein wenig ahnung von netzwerktechnik hat ... weiss das man den Puffer bis auf 1400 ausreitzen kann ... 1000 is gut 1400 besser

    send, recv haben rückgabe werte ... (fehlererkennung!) ... also wenns nich klick macht ...
    der rückgabe wert ist >0 wenn es OK ist UND gibt die anzahl der bytes wieder ...:

    if(send(socket, (const char*)buf,1000,0)!=1000)
    {
        //fehler
    }
    

    sollte da mal das minimum sein

    dann ne datei auslessen ...

    ist es nicht günstiger es so zu machen
    for( int i=0;i<abs(dateigrösse/1000);i++)
    {
    in den buffer lessen
    senden^^
    }
    den letzten rest lesen ...
    und senden

    ?

    am besten ist es noch wenn du die aktuelle postion mit übergibst ... und probier mal ne testdatei aus wo 00 01 02 03 ... ff 00 01 ... drine steht?!
    da siehste welches byte nicht übertagen wird 😉



  • Ich möchte nochmal auf hustbaer's Hinweis hinweisen, bevor der untergeht 😉

    hustbaer schrieb:

    keks. send() sendet nicht immer genausoviel wie man übergibt, sondern bloss soviel wie die sockets implementierung gerade lust hat. steht in der doku. für recv gilt dasselbe. lies es nach 😉

    MSDN schrieb:

    If no error occurs, send returns the total number of bytes sent, which can be less than the number requested to be sent in the len parameter.

    http://msdn2.microsoft.com/en-us/library/ms740149.aspx

    ...ähnliches steht bei recv(). Damit scheint hier im Board jeder zweite Winsock-Thread zu tun zu haben 😉
    z.B. war der letzte dieser:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-174355-and-start-is-0.html



  • hustbaer schrieb:

    nep schrieb:

    Ähm noch was anderes: Es ist doch glaube ich nur so, dass die Bytes, welche durch einen Aufruf mit send verschickt werden in korrekter Reihenfolge ankommen. Es ist aber nicht garantiert, dass die Bytes welche durch mehrere send-Aufrufe verschickt werden, auch genau in der Reihenfolge der Aufrufe ankommen. Oder irre ich mich da jetzt? (Alles natürlich auf TCP Sockets bezogen)

    Du hast TCP geschrieben, und TCP impliziert nunmal nen stream socket (SOCK_STREAM). Bei stream sockets ist es eben so wie ich geschrieben habe, also dass send() nur soviel verschickt wie es gerade lustig ist, dafür ist allerdings 101% garantiert dass die Daten in der richtigen Reihenfolge am anderen Ende rauskommen.

    Bei nem datagram socket (SOCK_DGRAM, das wäre dann z.B. UDP statt TCP) ist es eben andersrum, d.h. entweder verschickt send() alles was man übergeben hat oder garnix, dafür ist NICHT garantiert dass irgendwas in der Reihenfolge ankommt wie es gesendet wurde.

    Du musst die Doku schon aufmerksam lesen, und nachlesen wenn da etwas steht wo dir nicht klar ist was es bedeutet bzw. ob es auf dein Programm zutrifft -- eben sowas wie "For message-oriented sockets" (was eben einen "datagram socket" beschreibt, und damit niemals auf TCP zutreffen kann).

    Äh und? Das was ich meinte hat doch gar nix damit zu tun, wie bzw. wann send() nun seine Daten verschickt. Das war was ganz anderes. Ausserdem hab ich hier doch gar kein Problem mit "meinem" Programm. Wollte nur was anmerken, wobei ich mir eben unsicher war ob das überhaupt stimmt. Wenn ich das so wirklich bräuchte würde ich schon die Doku lesen, keine Sorge... Übrigens ist mit der Unterschied zwischen UDP und TCP sehr wohl bewusst...



  • kan sein das er alles schickt kann sein das er nur 1 byte schickt)

    wie jetz? TCP is ein sehr sehr häufige methode zur datenübertragen un wird auch von grossen organisationen wie icq,steam usw benutzt un es kann sein dass von 1000 byte nur einer geschickt wird??

    also ich benutze SOCK_STREAM un wenn ich die eigenIP (127.0.0.1) angib wird die datei problemlos un vollständig von meinen pc auf meinen pc geschickt. daraus habe ich geschlossen dass kein fehler mit dateiarbeit (und verbindungsinitaliesierung vll auch) vorliegen kann.

    also ich finde diese "methode" ein datei zu übertragen um es sanft aus zu drücken ... zum scheitern verurteilt ...

    aber wie wird sowas dann mit TCP gemacht?

    ich hab die verbindungsinitalisierung relativ formel gemacht.
    socket erstellen. zu host verbinden un dann schickroutine
    bzw
    socket erstellen. listen. akzeptieren. un dann schickroutine.

    also ich versuch mal alle debuganstösse auszufürhen un ihr hört wieder von mir^^



  • wie wäre es wenn du einfach die größe der zu erwartenden daten (dateigröße oder what ever) als integer vorausschickst, am client auf genau einen integer wartest (4-8 zusammenhängende bytes werden schon drinn sein, ich denk nicht das wirklich nur 1 byte ankommt, aber egal) den dann liesst und in einer schleife solanbge empfängst bis du deine daten auch 100%ig hast oder dein recv = 0 oder -1 ergibt dann haste nen socketclose btw. fehler.



  • nep schrieb:

    hustbaer schrieb:

    nep schrieb:

    Ähm noch was anderes: Es ist doch glaube ich nur so, dass die Bytes, welche durch einen Aufruf mit send verschickt werden in korrekter Reihenfolge ankommen. Es ist aber nicht garantiert, dass die Bytes welche durch mehrere send-Aufrufe verschickt werden, auch genau in der Reihenfolge der Aufrufe ankommen. Oder irre ich mich da jetzt? (Alles natürlich auf TCP Sockets bezogen)

    Du hast TCP geschrieben, und TCP impliziert nunmal nen stream socket (SOCK_STREAM). Bei stream sockets ist es eben so wie ich geschrieben habe, also dass send() nur soviel verschickt wie es gerade lustig ist, dafür ist allerdings 101% garantiert dass die Daten in der richtigen Reihenfolge am anderen Ende rauskommen.

    Bei nem datagram socket (SOCK_DGRAM, das wäre dann z.B. UDP statt TCP) ist es eben andersrum, d.h. entweder verschickt send() alles was man übergeben hat oder garnix, dafür ist NICHT garantiert dass irgendwas in der Reihenfolge ankommt wie es gesendet wurde.

    Du musst die Doku schon aufmerksam lesen, und nachlesen wenn da etwas steht wo dir nicht klar ist was es bedeutet bzw. ob es auf dein Programm zutrifft -- eben sowas wie "For message-oriented sockets" (was eben einen "datagram socket" beschreibt, und damit niemals auf TCP zutreffen kann).

    Äh und? Das was ich meinte hat doch gar nix damit zu tun, wie bzw. wann send() nun seine Daten verschickt. Das war was ganz anderes. Ausserdem hab ich hier doch gar kein Problem mit "meinem" Programm. Wollte nur was anmerken, wobei ich mir eben unsicher war ob das überhaupt stimmt. Wenn ich das so wirklich bräuchte würde ich schon die Doku lesen, keine Sorge... Übrigens ist mit der Unterschied zwischen UDP und TCP sehr wohl bewusst...

    *räusper* Tschulligung, hab nicht geguckt wie der OP heisst, und aufgrund der Formulierung vermutet es wäre dein Thread 🙂
    Vergiss also meine Antwort, richtige Antwort folgt nun:

    nep schrieb:

    Ähm noch was anderes: Es ist doch glaube ich nur so, dass die Bytes, welche durch einen Aufruf mit send verschickt werden in korrekter Reihenfolge ankommen. Es ist aber nicht garantiert, dass die Bytes welche durch mehrere send-Aufrufe verschickt werden, auch genau in der Reihenfolge der Aufrufe ankommen. Oder irre ich mich da jetzt? (Alles natürlich auf TCP Sockets bezogen)

    Du irrst dich. Das ist garantiert (bei stream Sockets, also TCP, wie du eben schreibst). Weiss nicht was daran so kompliziert ist -- heisst ja "stream" und nicht "partially ordered stream" oder so 😉

    Was du schreibst trifft im Übrigen auf datagram Sockets (UDP) zu, da werden die einzelnen Bytes eines Paketes auch nicht durcheinandergewürfelt -- wäre ja komplett unbrauchbar. Dort gilt dann auch dass die Reihenfolge der einzelnen Pakete nicht garantiert wird, bzw. nichtmal dass die überhaupt ankommen...



  • (naja, die Pakete an sich könnten rein-theoretisch schon ungeordnet durch die Leitungen schwirren, aber wir befinden uns hier auf ganz anderer Ebene und kriegen davon eh nix mit - Das wird voher schon für uns in richtiger Reihenfolge zusammengesetzt ;D)

    Bei recv() kommen die Bytes auf jedenfall in der Reihenfolge wie sie gesendet wurden an 😉



  • hustbaer schrieb:

    nep schrieb:

    Ähm noch was anderes: Es ist doch glaube ich nur so, dass die Bytes, welche durch einen Aufruf mit send verschickt werden in korrekter Reihenfolge ankommen. Es ist aber nicht garantiert, dass die Bytes welche durch mehrere send-Aufrufe verschickt werden, auch genau in der Reihenfolge der Aufrufe ankommen. Oder irre ich mich da jetzt? (Alles natürlich auf TCP Sockets bezogen)

    Du irrst dich. Das ist garantiert (bei stream Sockets, also TCP, wie du eben schreibst). Weiss nicht was daran so kompliziert ist -- heisst ja "stream" und nicht "partially ordered stream" oder so 😉

    Was du schreibst trifft im Übrigen auf datagram Sockets (UDP) zu, da werden die einzelnen Bytes eines Paketes auch nicht durcheinandergewürfelt -- wäre ja komplett unbrauchbar. Dort gilt dann auch dass die Reihenfolge der einzelnen Pakete nicht garantiert wird, bzw. nichtmal dass die überhaupt ankommen...

    Ja das hat Ceos weiter oben schon geschrieben 😉 Wie gesagt sollte nur ein Einwurf sein, den ich aber extra nochmal hinterfragt habe, weil ich mir da selbst unsicher war wie das genau aussieht (und zu faul zum Doku lesen war 😉 ).
    Und nochmal, ich kenn den Unterschied zwischen UDP und TCP... das was du schreibst stimmt ja auch, aber das hat so eigentlich gar nix mit meinem "Einwurf" zu tun. Wenn du UDP Sockets hast, kannst du ja eh nur so viele Daten an send() geben, wie die maximale UDP Packet-Größe beträgt (müssten so ~64 Kb sein). Und das die Bytes in einem Packet nicht durcheinandergewürfelt werden ist ja wohl logisch...



  • Fachmann schrieb:

    aber wie wird sowas dann mit TCP gemacht?

    Du müsstest quasi deine send()-Routine austauschen gegen eine send_really() oder so. Ähnlich hat das ja derjenige in dem oben genannten Thread auch gelöst.
    Quasi sicherstellen das send() bzw. recv() wirklich alles sendet.

    Sagen wir du willst 10 Bytes verschicken und rufst send() auf. send() meldet es hätte 2 Bytes verschickt. Also weisste das noch die restlichen 8 Byte hinterher müssen. Also send() mit den restlichen 8 Bytes nochmal aufrufen.
    Diesmal sagen wir mal hätte send() 7 Bytes verschickt. Fehlt also noch einer. Den kriegste dann mit dem letzten send() weg.
    Quasi ne kleine Schleife und nen byte-Pointer einfach weitersetzen bis alles weg ist.

    Ähnlich ist es bei recv() 😉

    Evtl. interessant ist da auch:
    http://msdn2.microsoft.com/en-us/library/ms740565.aspx



  • Sagen wir du willst 10 Bytes verschicken und rufst send() auf. send() meldet es hätte 2 Bytes verschickt. Also weisste das noch die restlichen 8 Byte hinterher müssen. Also send() mit den restlichen 8 Bytes nochmal aufrufen.
    Diesmal sagen wir mal hätte send() 7 Bytes verschickt. Fehlt also noch einer. Den kriegste dann mit dem letzten send() weg.
    Quasi ne kleine Schleife und nen byte-Pointer einfach weitersetzen bis alles weg ist.

    Das ist aber auch am thema vorbei!!!
    Send sendet (eigentlich) IMMER ALLES was übergeben wurde.
    Nur muss das erfolgreiche senden des Array nicht heissen das auch alle bytes in einem schwung gesendet wurden. Der Socket arbeitet in einem ganz anderen kontext als dein programm, du schiebst praktisch nur die bytes in die queue.
    Wenn du grad 40 von 100 bytes in den puffer geschreiben hast, kann es passieren das der socket anfängt zu schreiben.
    die send methode wird dadurch nicht unterbrochen, sie blockiert nur (im nanosekundenbereich denk ich).
    nun sind 40 bytes gesendet, die sendfunktion setzt fort und kopiert die restlichen 60 byte.
    Die Send funktion meldet 100 geschreibene bytes und dennoch kommen am client 2 "pakete" 1 40bytes das andere 60bytes

    falls dem so nicht ist bitte ich um verzeihung, ich habde das von unserem Java-Dozenten, der mir ehrlich gesagt ein wenig zu viel wissen will


Anmelden zum Antworten