Nope, ist auch nicht sinnvoll. Willst du, dass dir das andere Ende den Speicher vollmüllen kann, wie es will? Es ist ja sowieso gängige Praxis ein gewisses Größenlimit für ein Packet im Protokoll festzusetzen - wieso sollte der Buffer da dynamisch sein? Ist ja nicht so, dass die Daten, die nicht in dieser Iteration in den Buffer passen, verloren gehen. Die liest man dann halt im nächsten Durchgang.
Ist ja beim Lesen von Dateien auch nicht anders, da gibt man ja auch an, wie viele Bytes man lesen möchte.
Eine Art konstanten Datenstrom wie beispielsweise std::cin kann man ja einfach als Wrapper um die lowlevel Funktionen implementieren.
Alternativ kannst du erst zwei Bytes lesen welche für die Größe verantwortlich sind, anschließend dann anhand dieser zwei Bytes dir die die Länge des Packets verraten den Rest, solange eine gewisse Maximalgröße nicht überschritten wird.
Alternativ kannst du erst zwei Bytes lesen welche für die Größe verantwortlich sind, anschließend dann anhand dieser zwei Bytes dir die die Länge des Packets verraten den Rest, solange eine gewisse Maximalgröße nicht überschritten wird.
^
Normalerweise haben Protokolle sowieso noch gewisse Zeichen festgelegt, die signalisieren dass eine Sequenz komplett/beendet ist. Du liest einfach so lange bis du das Zeichen hast die Daten ein und speicherst sie in einem anderen Vector den du auch außerhalb der Funktion nutzen kannst.
In beiden Fällen hat man aber einen statischen Buffer, den man iterativ neu befüllt. Bloodx wollte wissen, ob man Daten empfangen kann, ohne eine maximale Buffergröße anzugeben. Zumindest entnehme ich das seiner Frage nach einem dynamischen Buffer und der Tatsache, dass er seine Schleife nicht schön findet.
Ob man die Trennung des Datenstroms dann mithilfe von magischen Trennsequenzen, statisch Packetgrößen oder einem Größenpräfix löst, ist ja sowieso dem Entwickler überlassen und hängt z.B. vom Anwendungsgebiet ab. Manche bieten sich gut für magische Sequenzen an, bei anderen passt das überhaupt nicht und ein Größenpräfix ist die Lösung.
In beiden Fällen hat man aber einen statischen Buffer, den man iterativ neu befüllt. Bloodx wollte wissen, ob man Daten empfangen kann, ohne eine maximale Buffergröße anzugeben. Zumindest entnehme ich das seiner Frage nach einem dynamischen Buffer und der Tatsache, dass er seine Schleife nicht schön findet.
Wie willst du die Dynamik sonst hineinbringen? Du hast seine Frage ja schon korrekt beantwortet, Shawak und ich haben nur das ergänzt was für manche vielleicht nicht so offensichtlich ist.
@bloodx
Wieso willst du das Socket schließen wenn keine Bytes gelesen wurden? Ich kenne die Implementierung deiner Library nicht aber wenn du vom Socket liest und feststellst, dass dir inzwischen niemand etwas gesendet hat, wirst du vermutlich in diesem Moment 0 Bytes empfangen haben (weil 0 Bytes gelesen wurden). Möchtest du dann wirklich die Verbindung trennen?
Ob und wann ein Packet deinen Anforderungen nicht enspricht, entscheidest du. Wie ist eigentlich egal - du kannst auch den Inhalt prüfen.
machen um direkt irgendwelche Phantasie Packets zu entfernen ?
Mit der Size auslesen hatte ich auch bereits überlegt, aber dann muss ich ja 2x recv'n ? Fand ich auch nicht sooo super, trotzdem Danke
Du scheinst die Funktionsweise von recv etwas misszuverstehen. Letztendlich kannst du das wirklich mit einer ReadFile Funktion vergleichen, nur dass du nicht von der Festplatte, sondern vom Netzwerkpuffer liest. Dabei blockiert die Funktion, wenn es nichts zu lesen gibt und hört dann auf zu lesen, wenn der aktuelle Lesevorgang beendet ist (die maximale von dir erlaubte Anzahl an Bytes wurde erreicht, die Verbindung wurde geschlossen, das System hat entschieden, dass erstmal genug empfangen wurde, ...), belässt die eventuellen restlichen Bytes im Puffer und macht dort beim nächst recv Aufruf direkt weiter. Diese Daten haben für send/recv keinerlei Struktur, es ist lediglich ein Strom von Bytes.
Wenn du auf der Senderseite 1 Packet (im Sinne deiner definierten Packetstruktur) verschickst, bedeutet das nicht zwangsläufig, dass es direkt in einem Stück ankommt. Ebenso bedeuten 2 Packets nicht gleich, dass du zwei recv Aufrufe brauchen wirst.
Du schreibst die Bytes auf der einen Seite in den Puffer rein und nimmst sie auf der anderen raus.
Worauf ich hinaus will: Wenn du mehr als 1024 Bytes im Puffer hast, heißt das nicht gleich, dass dort ein Fantasiepacket gesendet wurde. Es können auch einfach bereits mehrere Packets angekommen sein (sofern dein Protokoll nicht vorsieht, dass ein weiteres Packet erst nach einer Antwort des Servers kommen darf). Der Puffer, den du für recv als Zwischenspeicher angibst, ist nicht gleichzusetzen mit einem fertigen Packet; seine Größe ist ebenso wenig wie die Anzahl der empfangenen Bytes gleichzusetzen mit der Größe eines Packets. Es ist nur ein Zwischenspeicher. Die Packets musst du dir selbst zusammenbauen bzw. diesen Datenstrom sinnvoll in diese aufteilen.
Dementsprechend kann deine Struktur z.B. so aussehen:
Code:
const int MAX_DATA_SIZE = 100;
struct Packet
{
int magic_signature;
int protocol_version;
int packet_id;
int data_size;
char[MAX_DATA_SIZE];
};
Dein Puffer muss nun nicht zwingend sizeof(Packet) groß sein, du kannst aus Effizienzgründen durchaus mehr auf einmal lesen:
Code:
std::vector<Packet> received_packets;
const int MAX_BUFFER = 1024;
char buffer[MAX_BUFFER];
int buffer_pos = 0;
while ((int recv_bytes = recv(socket, buffer + buffer_pos, MAX_BUFFER - buffer_pos, 0) > 0)
{
int processed_bytes = 0;
//solange vollständige Packets extrahiert werden können
while (recv_bytes - processed_bytes >= sizeof(Packet))
{
Packet temp = *(Packet*)(buffer + processed_bytes);
if (temp.magic_signature == 1337 && temp.protocol_version == 1 && temp.data_size <= MAX_DATA_SIZE)
{
received_packets.push_back(temp);
}
else
{
//issue error
}
processed_bytes += sizeof(Packet);
}
//Rest an den Anfang des Puffers schieben und im nächsten Durchlauf weitermachen
memcpy(buffer, buffer + processed_bytes, recv_bytes - processed_bytes);
buffer_pos = recv_bytes - processed_bytes;
}
(ich weiß, ist kein schönes C++ bzw. ein C/C++ Mix, schlagt mich doch :<)
In diesem Beispiel habe ich der Einfachheit halber mit einer statischen Packetgröße gearbeitet (obwohl der genutzte Platz (data_size) innerhalb des Packets natürlich je nach Packet ID variieren kann).
Mit diesen fertig zerstückelten Packets kann man dann auch anständige Plausibilitätsprüfungen durchführen, so wie ich es dort exemplarisch mit ein paar typischen Bestandteilen eines Packets tue.
Quote:
Mit der Size auslesen hatte ich auch bereits überlegt, aber dann muss ich ja 2x recv'n ? Fand ich auch nicht sooo super, trotzdem Danke
Damit sollte auch das geklärt sein: Nein, musst du nicht. Du rufst recv immer gleich auf und das hat nichts mit der Anzahl oder der Größe von Packets zu tun. Du baust du dir erst aus dem empfangenen Strom zusammen und erst dort findet die Interpretation von irgendwelchen mitgesendeten Größen und was nicht alles statt.
received_packets kann dann an irgendwelche Callbacks zur Weiterverarbeitungen gegeben werden.
Quote:
Wie willst du die Dynamik sonst hineinbringen? Du hast seine Frage ja schon korrekt beantwortet, Shawak und ich haben nur das ergänzt was für manche vielleicht nicht so offensichtlich ist.
Gar nicht, der Puffer wird immer statisch bleiben.
Quote:
Wieso willst du das Socket schließen wenn keine Bytes gelesen wurden? Ich kenne die Implementierung deiner Library nicht aber wenn du vom Socket liest und feststellst, dass dir inzwischen niemand etwas gesendet hat, wirst du vermutlich in diesem Moment 0 Bytes empfangen haben (weil 0 Bytes gelesen wurden). Möchtest du dann wirklich die Verbindung trennen?
Wenn recv 0 zurückgibt, wurde die Verbindung von der anderen Seite geschlossen. Man kann nicht 0 Bytes empfangen, da recv eine blockierende Funktion ist, sprich sie wartet ggf. auf Input.
recv ist übrigens die Standardfunktion zum Empfangen auf Windows und Unix-Systemen.
Gar nicht, der Puffer wird immer statisch bleiben.
Streng genommen ja, aber wenn man den statischen Vektor in der Klasse schön pflegt, kann man sogar dynamisches Verhalten erzeugen (ändert natürlich nix daran dass er statisch ist). Das meinte ich damit, war vielleicht etwas blöd formuliert.
Quote:
Originally Posted by MrSm!th
Wenn recv 0 zurückgibt, wurde die Verbindung von der anderen Seite geschlossen. Man kann nicht 0 Bytes empfangen, da recv eine blockierende Funktion ist, sprich sie wartet ggf. auf Input.
Ah ok, bin von boost etwas anderes gewöhnt, da hatte ich immer die asynchronen Funktionen genutzt.
Quote:
Originally Posted by MrSm!th
recv ist übrigens die Standardfunktion zum Empfangen auf Windows und Unix-Systemen.
... die ich nie genutzt habe weil ich stattdessen fertige Netlibs wie die von boost genommen habe.
Und was ist jetzt die Frage?
So wie du das machst, kann das übrigens ziemlich nach hinten losgehen. Zum einen erzeugst du ein Memory Leak (ich würde generell nicht mehr auf new/delete setzen, seit es C++11 gibt), zum anderen hast du keine Garantie, dass du ein vollständiges Packet in deinen Puffer bekommst, wie bereits oben erklärt. Deshalb musst du prüfen, ob du ein vollständiges und plausibles Packet hast.
[Selling] [SG] LV 87 Warrior 3P + LV 90 Buffer, Lv 76 Sura + lvl 70 Buffer 03/16/2014 - Metin2 Trading - 8 Replies Hi,
Ich verkauf hier meine Chars auf Metin2.SG
Tradeadministrator :
dust oder wer online ist
Ingame name(en):
Kurdboy verheiratet mit Vexina, BugattiStyle verheiratet mit Custombuffer
Dynamischer Pointer wtf? 03/14/2014 - C/C++ - 4 Replies Hallo,
ich brauche für ein Spiel 2 adressen. Diese sind dynamisch weswegen ich mich gleich an die pointersuche gemacht habe. Der 1 Pointer geht auch wunderbar, aber der 2 ist sozusagen statisch . Die Pointer zeigen einfach nach den neustart auf bullshit undzwa jeder von ihnen und der rest auf garnix.
Womit könnte das zu tuhen haben ?
[Realese] Flyff buffer für homepage buffer server 04/01/2011 - Flyff Private Server - 7 Replies Hallo dies ist mein erstes tool ein flyff buffer für p-server die einen homepage buffer haben
1. den changejob ordner in eure appserv/www verschieben
http://biffi.bplaced.net/pic1.png
2. die config.html mit editor öffnen und eure ip eintragen
http://biffi.bplaced.net/pic2.png
Tinyproxy mit dynamischer IP 11/12/2010 - Technical Support - 3 Replies Ich habe auf meinem Server tinyproxy laufen. Allerdings habe ich keine Lust, jedesmal, wenn sich meine IP ändert (jeden Tag!), die Configdatei anzupassen. Gibt es eine Möglichkeit, das zu umgehen?
Vielen Dank im Vorraus,
abba232
[Question] Hooking send() & recv() works, but recv hiding data for co??? 05/06/2009 - CO2 Programming - 2 Replies Hey guys, I've been making a DLL to allow another program to intercept the packets of conquer using windows pipes. (Then its the job of the main program to decrypt the packets, the DLL only gives a communication channel for the main program)
(winsock functions btw)
- hooking send() works fine for my internet browser
- hooking recv() works fine for my internet browser
- hooking send() works fine for conquer online