CAsyncSocket - zwei Strings senden und einen empfangen

Bastian N

Grünschnabel
Hallo Leute,

ich bin neu hier also seid erstmal gegrüßt.
Am besten ich fange ganz vorne an, um mein Problem zu schildern. Ich habe mit CAsyncSocket eine Verbindung zwischen zwei Geräten aufgebaut und das funktioniert soweit auch alles super. Nun übertrage ich aber sehr viele daten die relativ schnell hintereinander gesendet werden.
So und nun das Problem: Wenn ich zwei Strings hintereinander sende kommen sie bei meinem Empfangsgerät ab und zu als ein String an und ich weiß nicht warum oder was ich dagegen machen kann. Ich wollte den String auf der Empfängerseite eigentlich nicht erst auseinander nehmen müssen. Hat vielleicht irgendjemand eine idee oder einen ansatz für das Problem?

Hab in einem englischsprachigen Forum schon mal was ganz altes gefunden, die meinten man könnte "select()" verwenden. Ich weiß aber nicht wirklich was die meinten, vielleicht hilft es einem von euch.

Ich danke euch schonmal im Vorfeld für eure Mühen

Gruß Bastian
 
Hat vllt. inzwischen jmd. ne Idee?
Häng momentan am gleichen Problem und das mit ::Sleep(50);(o.ä.) zu lösen ist nicht grad zuverlässig (oder?)
Aber zumindest hab ich inzwischen gerafft wieso ich mit den Daten manchmal was anfangen kann, manchmal nicht.
Wie wäre die Option eines Gegensignals? (OOB Data oder einfach n "OK" string)
Besteht die Option auf den nächsten "OnReceive" zu warten oder so?
Mir fehlen Ideen.

Gruß Dave
 

Endurion

Erfahrenes Mitglied
Du darfst nie davon ausgehen, das etwas, das du als Stück in einen Socket schiebst, auf der Gegenseite als genau dieses Stück wieder rauskommt.

Das kann wie in deinem Fall mit dem nächsten Stück zusammengehängt oder aber auch in Einzelteilen ankommen. Was garantiert ist, dass nichts verlorengeht und das alles in der richtigen Reihenfolge ankommt (bei TCP).

Üblicherweise baut man ein Paket um eine Nachricht drumrum. Darin ist dann meistens die Länge der Daten mit angegeben. So kann man auf der Gegenseite den Bytehaufen (nichts anderes sind die Daten) wieder ordnungsgemäss zerlegen.
 
D.h. von der Korrekten Reihenfolge kann ich auch ausgehen und ich Markier einfach "ANFANG" und "ENDE" des jeweiligen Pakets auf ieine Weise? (bei willkürlicher reihenfolge zu willkürlicher zeit wäre ein zusammsetzen des Paketes ja generell unmöglich(?)?)

Kann getrost ignoriert werden, hab den Satz
Was garantiert ist, dass nichts verlorengeht und das alles in der richtigen Reihenfolge ankommt (bei TCP).
überlesen, danke dir :)

Aber trotzdem noch eine Frage ist ein "Warten auf den nächsten Datenerhalt" möglich?
Das würde mir noch ne ganze Menge Arbeit ersparen :)

So long, Dave
 
Zuletzt bearbeitet:

Endurion

Erfahrenes Mitglied
Ich kenne mich jetzt mit CAsyncSocket nicht so dolle aus. Aber da gehe ich mal stark von Windows aus (ist ja auch MFC hier).

Da war "select" nicht so verkehrt. Damit kann man einen (oder mehrere) Socket unter anderem abfragen, ob Daten zum Lesen vorliegen. Das heisst beim CAsyncSocket AsyncSelect.

Damit kannst du ein Event für FD_READ aktivieren. Sobald Daten vorliegen, bekommst du OnReceive aufgerufen.
Etwas aufwendiger, aber IMHO weniger CPU-fressend: Du kannst auch
 
uhm ... kannst du das 2te Beispiel komplett austippen? ;)

Jup select(FD_READ) gibt mir n Callback auf OnReceive(), was zwar wunderbar günstig ist wenn ich Daten bekomm (wird bereits genutzt) aber leider keine möglichkeit bietet explizit auf Daten zu warten.

Folgendes Konstrukt:
X sendet Daten an Y
Y Bestätigt nach einer Statusabfrage
X empfängt Statusabfrage
X wertet Statusabfrage aus
X sendet Reaktion an Y

Klar lässt sich das im OnReceive beschreiben, aber die wird dann halt doch (imho) recht schnell unübersichtlich, darum hab ich nach ner möglichkeit gesucht ihm quasi sowas zu sagen:
X:
Code:
CAsyncSocket sSender;
[...]
sSender.Send("test", sizeof("test"));
while(sSender.NoDataRecieved())
{;}
sSender.Send("test2", sizeof("test2"));
Problem ist nur eine auf die Art laufende Endlosschleife ist
a) nicht besonders hübsch,
b) blockiert sie mir die Windows Messages, d.h. OnReceive kann nicht ausgelöst werden.
 

Endurion

Erfahrenes Mitglied
Sorry wegen dem abgeschnittenen Text, der letzte Satz sollte komplett raus :)

Ich verwende bei mir direkt die Sockets mit Winsock2 und dann kann die Funktion WSAEventSelect verwendet werden. Damit kannst du Winsock ein Event-Handle geben, das bei bestimmten Ereignissen gesetzt wird.

Damit kann man dann WaitForMultipleObjects aufrufen, das wartet dann, bis das Event gesetzt wird. Da muss man dann allerdings auch mit Threads arbeiten.
 
Völlig simple Lösung ohne Thread

Code:
while(iLen <= 0)
{
        iLen = this->d_sSender.Receive(pBuffer, 4);
	iTransferSize = ::atol(pBuffer);
	iLen = this->d_sSender.Receive(pBuffer, iTransferSize);
	pBuffer[iLen] = '\0';
	Sleep(20);
}

Ich war viel zu fixiert auf die Events, obwohl ich die in diesem Fall ja überhaupt nicht brauch ;)
Sinn und Zweck ist ja "blockiere, bis du Antwort erhälst". Nun besteht zwar die Gefahr eines Deadlocks wenn die Gegenseite nicht mehr mitspielt oder Crap sendet, aber das lässt sich ja mit nem Timeout abfangen.

Dank dir trotzdem für die Hilfe :)