Hoe de capaciteit van een TCP-verzendbuffer te controleren om de levering van gegevens te garanderen

Ik wil graag bezorgbevestiging toevoegen aan mijn TCP-interface. Een niet-blokkerende schrijf kan de verzendbuffer vullen, maar de gegevens kunnen nooit aankomen als de verbinding mislukt - ondertussen heeft schrijven gerapporteerd dat de gegevens zijn ontvangen (door de lokale socket).

Als ik extra acks aan de stapel heb toegevoegd, kon ik controleren of elk gegeven werd ontvangen. Ik denk dat FTP dit doet. Maar ik kan iemands code niet lenen en wil liever niet ack/opnieuw implementeren, vooral omdat TCP het meeste hiervan al doet.

Ik denk dat het kan worden bereikt als ik kan controleren of de buffer voor socketverzending leeg is na elke write (). Als er geen gegevens meer zijn, moet deze allemaal zijn afgeleverd. Ik let niet op de latency van het legen van de buffer.

Bewerken: Ik realiseer me dat TCP/socket-implementaties per systeem verschillen, maar als er een Berkeley- of Linux-oplossing is, is deze waarschijnlijk beschikbaar voor mij.

Bewerken: om een ​​aantal suggesties aan te pakken, wil ik drie niveaus van de TCP-interface implementeren, waar ik niet weet hoe ik de *''de moet bereiken.

  • Normaal TCP zonder leveringszekerheid, voor toepassingen die gevaarlijk willen leven.
  • * TCP dat de ontvangst verifieert door een externe host, zelfs als het pakket nooit is afgeleverd in de externe app. Dit vermindert het grootste deel van mijn verbindingsrisico (mobiele client) en kan volledig aan de clientzijde worden geïmplementeerd. Ik denk dat dit kan worden geïmplementeerd als ik kan controleren of de socket uitgaande buffer leeg is.
  • Toepassingslaag ACK en opnieuw verzonden geïmplementeerd bovenop TCP of UDP, zodat de eindpunten worden geverifieerd.
0

2 antwoord

Eigenlijk is het zoeken naar dingen op toepassingsniveau de enige manier . Hier zijn een paar problemen:

  • When you send data, even if it leaves your kernel it's not done until your TCP receives an ACK about it. The API doesn't provide you with this information.

  • The fact that your application received an ACK can mean:

    • The remote kernel (not the application) received the data. There's no telling if the remote process called recv. Maybe it crashes before getting a chance to recv.
    • Some proxy (MANY cheap devices do this) is talking to you and is using a separate connection with the true receiver. You received the ACK but you don't know if the remote system has it. And if the remote system has it, read the bullet above.

Tot slot:

  • U hebt geen toegang tot TCP ACK s
  • Zelfs als u toegang tot hen zou hebben, zouden ze nutteloos zijn

U hebt dus een ACK op applicatieniveau nodig, maar natuurlijk zonder hertransmissies . De ACK moet u alleen vertellen "Ik heb uw gegevens ontvangen en verwerkt".

BEWERK

Ik zie dat je blijft volharden in je idee. Ga op zoek naar SIOCOUTQ zoals beschreven in enkele Linux manual-pagina's. Natuurlijk is het Linux-onlye, maar kijk of het doet wat je nodig hebt.

9
toegevoegd
@mr_dude Ik heb mijn antwoord bewerkt.
toegevoegd de auteur cnicutar, de bron
Ik had overwogen dat de gegevens die de externe socket bereikten niet noodzakelijkerwijs zouden worden gelezen, maar hadden niet overwogen dat een proxy ook een faalpunt zou kunnen zijn. Dit is erg handig, maar ik zou nog steeds willen dat ik kon verifiëren dat mijn gegevens op zijn minst een een eindpunt bereikten, als het mogelijk is. Natuurlijk heb ik geen toegang tot ACK's, maar hopelijk wordt ik er eenvoudiger door het verifiëren van een lege verzendbuffer.
toegevoegd de auteur mr_dude, de bron
Yep, SIOCOUTQ is precies wat ik nodig heb. Helaas ondersteunt mijn ioctl-implementatie dit niet, hoewel het misschien onder een andere naam staat. Bedankt, ik hoop dat mijn bewerking hierboven en de onderstaande opmerking aantonen dat ik deze aanpak moet pushen. Ik zal deze thread nog een paar uur geven voor het geval iemand weet van een andere benadering, schakel dan deze oplossing in.
toegevoegd de auteur mr_dude, de bron

TCP zorgt alleen voor bezorging op OS-niveau. Dit betekent bijvoorbeeld dat als uw ontvangertoepassing onverwacht midden in de verzending crasht, uw afzender er niet zeker van kan zijn dat alle gegevens zijn ontvangen - houd er rekening mee wanneer de externe TCP-stack gegevens over ontvangt, maar uw toepassing niet krijg een kans om deze gegevens te verwerken.

Daarom is het mogelijk dat u een bevestigingschema op toepassingsniveau nodig hebt. U kunt bijvoorbeeld dezelfde techniek gebruiken als TCP-stack - gebruik APN-nummers, alleen deze keer op toepassingsniveau. Als uw externe app u antwoordnummer X stuurt, weet u zeker dat X-gegevensitems inderdaad worden ontvangen en verwerkt door app , niet door OS TCP-stack .

2
toegevoegd
Ja, die meer robuuste implementatie is mogelijk, maar op dit moment ben ik meer bezig om ervoor te zorgen dat de uitgaande gegevens door iemand als zijn geacteerd. In het bijzonder ben ik op een mobiel apparaat, dus het belangrijkste punt van mislukking is mijn netwerkverbinding, de externe host en de applicatie zijn betrouwbaar genoeg.
toegevoegd de auteur mr_dude, de bron