Forum: PC-Programmierung Client sendet ohne accept von Server


von Asio (Gast)


Lesenswert?

Hallo,

noch eine kleine Frage zu Boost Asio, mir ist aufgefallen, dass sobald 
im Server ein Acceptor-Objekt angelegt wird sofort alle Clients sich 
connecten können und auch Daten schicken können selbst wenn im Server 
noch kein accept aufgerufen wurde.

// im Server:
1
tcp::acceptor acceptor{ioservice, tcp_endpoint};
2
//acceptor.accept(socket); // testweise wegkommentiert
3
//read(...)


// im Client:
1
boost::asio::connect(socket, resolver.resolve(q)); 
2
write(socket,buffer);

Was mich wundert ist:
Wenn man im Server "acceptor.accept(socket);" testweise NICHT aufruft 
(nach dem Anlegen des acceptor-Objektes), dann connected der Client und 
kann erfolgreich die Funktion write(socket,buffer) ausführen obwohl im 
Server acceptor.accept(socket) noch nicht aufgerufen wurde (und kein 
read()).
Der Client tut also so, als wäre alles Verbunden und Daten werden 
vermeindlich erfolgreich gesendet (ich dachte bei write() wird dies 
validiert). Wieso ist das möglich?

Ich möchte eigentlich das der Client eine Exception bekommen solange im 
Server acceptor.accept(socket) noch nicht aufgerufen wurde oder eben 
irgendeine andere Kontrolle.

Grüße

von Hmmm (Gast)


Lesenswert?

Asio schrieb:
> dann connected der Client und kann erfolgreich die Funktion
> write(socket,buffer) ausführen obwohl im Server acceptor.accept(socket)
> noch nicht aufgerufen wurde (und kein read()).

Der Kernel nimmt TCP-Connections ab dem listen() an.

Erst nach dem TCP-Handshake, also wenn aus Client-Sicht bereits eine 
Verbindung besteht, holt sich der Server-Prozess per accept() einen 
verbindungsspezifischen Socket.

D.h. auch wenn der Name accept() etwas anderes impliziert, hat man damit 
keinerlei Einfluss darauf, ob eine TCP-Connection zustande kommt.

von Asio (Gast)


Lesenswert?

Danke für die Erklärung. Was ich allerdings noch nicht verstehe ist, 
dass nach listen() im Server auch ohne accept(), der Client Daten an den 
Server senden kann (aus seiner Sicht).

Ich bekomme einen korrekten Rückgabewert im Client von der Funktion 
write() auch wenn im Server kein accept() ausgeführt wurde (und so kein 
Server-Socket für einen Datenaustausch existiert). Das heißt der Client 
kann gar nicht feststellen, ob die Daten beim Server angekommen sind.

Ich dachte die Funktion write() blockiert, bis alles auf der Gegenseite 
angekommen ist aber nach meinem Test ist das aber nicht der Fall.
http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/write/overload1.html
Kann man irgendwie sicherstellen ob die gesendeten Dinge auch wirklich 
angekommen sind?

Gruß

von Hmmm (Gast)


Lesenswert?

Asio schrieb:
> Was ich allerdings noch nicht verstehe ist, dass nach listen() im Server
> auch ohne accept(), der Client Daten an den Server senden kann (aus
> seiner Sicht).

Es gibt auf beiden Seiten Queues, worin das erstmal landet.

> Kann man irgendwie sicherstellen ob die gesendeten Dinge auch wirklich
> angekommen sind?

Ein Protokoll verwenden, das sowas beinhaltet. Und immer damit rechnen, 
dass auch eine erfolgreich aufgebaute Verbindung mal unterbrochen werden 
kann, ohne dass das Betriebssystem das zeitnah mitbekommt.

von Asio (Gast)


Lesenswert?

Hmmm schrieb:
> Ein Protokoll verwenden, das sowas beinhaltet.

welches wäre das zum Beispiel?

Man könnte sich vielleicht auch einfach eine Empfangsbestätigung von der 
Gegenseite senden lassen. Kommt keine Bestätigung zurück (zB ein bool), 
dann weiß man sofort, dass auch nichts angekommen ist.

von Hmmm (Gast)


Lesenswert?

Asio schrieb:
> welches wäre das zum Beispiel?

Das ist schnell selbst entworfen. Stichworte:

- Greeting des Servers bei Verbindungsaufbau, z.B. auch mit der 
Protokollversion

- Authentifizierung des Clients, bevor Nutzdaten ausgetauscht werden

- ggf. Keepalives, wenn keine Daten ausgetauscht werden, mitsamt Timeout 
zur Erkennung abgebrochener Verbindungen

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.