Networking

devnator

Mitglied
Hey liebe Community,

Ich beschäftige mich seit ein paar Tagen mit Networking nun sind hier ein paar Fragen aufgetreten.
Ich hoffe ihr könnt mir hier weiter helfen.

Nun wenn ich über einen TCP Socket bytearrays sende aus was bestehen die 0 und 1 oder wie läuft das ab.
Und wenn ich was zum ByteArray mache mit .toByteArray wie wird das serializiert zu 0 und 1. Bin hier etwas verwirrt habe auch in google nichts brauchbares gefunden.

2.) Was steckt hinter der writeInt() methode von Java bei sockets. Normal muss man dem Server ja zuerst senden wie groß der danachfolgende ByteArray ist aber das liest man ja auch mit readInt() aus. #Brain****
Oder ist die int größe fest mit 4 bytes vorgegeben und er ließt bei readint 4 bytes aus wie gesagt ich bin verwirrt.

Ich hoffe ihr könnt mir bei den fragen helfen :)
 

InfectedBytes

Top Contributor
Das ganze hat nix mit AWT/Swing zu tun. Dein Thread sollte ins Networking Unterforum.

1.) Dein Bytearray ist einfach nur eine Folge von Bytes. Wie genau diese dann im Endeffekt serialisiert werden, ist für dich als Anwender im Grunde egal. Im Endeffekt werden über die Leitung die einzelnen Bits übertragen, wie genau dies passiert hängt zudem von der Übertragungsart ab WiFi/Ethernet/...
Falls es dich interessiert, schau dir für den Anfang mal den ISO/OSI stack an. Aber wie gesagt, wie genau die Serialisierung abläuft, kann dir eigentlich egal sein

2.) Ein Int ist nunmal eine 32 Bit Zahl und wird bei read/write Int auch einfach genau so in 4 Bytes zerlegt. Allerdings musst du aufpassen, wenn du readInt machst, wird halt versucht 4 Bytes zu lesen, falls aber eben keine 4 Byte vorhanden sind, gibts nen Fehler.
Außerdem musst du beachten, dass nicht alles sofort verschickt wird, sondern erst wenn der Buffer voll ist bzw. du manuel flush aufgerufen hat.
 

devnator

Mitglied
Danke für deine Antwort, ich würde aber trotzdem gerne wissen wie das serialisiert wird da normal ja networking stream mit 0 und 1 funktioniert könnte mir das bitte noch wer erklären?! :)
 

InfectedBytes

Top Contributor
Erstmal gibt Java nur die Zieladdresse und die Daten (als Bytefolge) an das System weiter. Dieses (und die Netzwerkkarte) kümmert sich dann um den Rest.

Die Serialisierung zu 0/1 ist ziemlich trivial, da ein Byte nunmal aus 8 Bit besteht und jedes dieser Bits ist entweder 0 oder 1.
Je nachdem worüber die Verbindung läuft (Ethernet, WiFi, etc.) wird gar nicht auf 0/1 runtergebrochen, sondern auf größere "Symbole".
Manche Modulationsverfahren verschicken z.B. 4 Bit als ein einzelnes Symbol. In Extremfällen, kann sogar ein ganzes Byte als ein einziges Symbol verschickt werden (oder sogar mehr).
 

Tobse

Top Contributor
Erstmal gibt Java nur die Zieladdresse und die Daten (als Bytefolge) an das System weiter. Dieses (und die Netzwerkkarte) kümmert sich dann um den Rest.

Die Serialisierung zu 0/1 ist ziemlich trivial, da ein Byte nunmal aus 8 Bit besteht und jedes dieser Bits ist entweder 0 oder 1.
Je nachdem worüber die Verbindung läuft (Ethernet, WiFi, etc.) wird gar nicht auf 0/1 runtergebrochen, sondern auf größere "Symbole".
Manche Modulationsverfahren verschicken z.B. 4 Bit als ein einzelnes Symbol. In Extremfällen, kann sogar ein ganzes Byte als ein einziges Symbol verschickt werden (oder sogar mehr).
Signed. Die Art der serialisierung hängt stark vom Medium ab; Wenn du z.B. einen Mehr-Frequenz-Sender hast kannst du problemlos ein Byte auf einmal übertragen (und dabei passiert garnix mit 0 und 1).

Wenn es dich interessiert, wie die verschiedenen Netzwerkgeräte miteinander kommunizieren (das ist auf der Byte-Ebene nämlich immer identisch) wenn du ein Byte-Array von Hamburg nach San Francisco schickst, ist das TCP Protokoll das, was du suchst.
 

devnator

Mitglied
@Tobse Ja das ist mir schon klar aber ein Integer besteht aus 4byte also 8 bits und 1 ist ein bit und 0 ist auch ein bit aber mit 32 bit lassen sich doch nicht alle zahlen der integer range darstellen oder ?
 
Zuletzt bearbeitet:

Tobse

Top Contributor
Nicht ganz richtig. Ein Byte besteht aus 8 bit. Ein Int besteht aus 4 Byte, ergo 4 * 8 = 32bit. Und mit 32bit sind exakt der Wertebereich eines Java-Integers.
Wenn du also writeInt(1234) aufrufst dann ergeben sich daraus 32 bit mit diesen Werten:

Code:
0000 0000 0000 0000 0000 0100 1101 0010
[Byte  1] [Byte  2] [Byte  3] [Byte  4]
        0         0         4       210

Diese 4 Byte gehen dann an die Netzwerkkarte. Und diese bildet sie dann, in welcher Form auch immer, auf ihr Medium (Elektromagnetische Wellen, Elektrische Impulse, Lichtimpulse, etc...) ab.


EDIT: Zu langsam gewesen...
 
Zuletzt bearbeitet:

devnator

Mitglied
Ja aber reichen 32 stellen aus um


−2.147.483.648
und


+2.147.483.647

zahlen darzustellen und wie erkennt man beim serializieren ob es plus oder minus ist
und warum sind es bei - .648 am schluss und bei plus .647
Danke für eure Hilfe :)
 

Tobse

Top Contributor
32bit reichen für die Zahlen von 0 bis 4.294.967.295 (beides einschließlich). Ein Bit ist für das vorzeichen: 0 positiv, 1 negativ. Dadurch werden aus den 32bit 31, und damit aus 4.294.967.295 2.147.483.647. 2.147.483.647 ist nicht gerade, weshalb auf der einen "Seite" "1 weg fällt". Das kannst du aber alles im Internet wunderbar nachlesen, stichwort "Binärdarstellung", "Binärdarstellung Fließkommazahlen" und "Zahlenkreis".
digital5_51.gif
 
Zuletzt bearbeitet:

devnator

Mitglied
Gut danke für die Antworte noch zu dem Bild:
-> mir ist nur die Skizze nicht ganz klar ich dachte immer es ist 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 und so weiter das wäre eben für 1 2 3 4 5 6 7 8 9 10 11 aber in diesem Kreis ist ab 8 irrgendwie das ganze Minus sorry aber ich bin jetzt komplett verwirrt xD

Bitte um eine Aufklärung :D
 

InfectedBytes

Top Contributor
das Beispiel im Bild geht auch nur von einer 4 Bit Zahl aus. und wie tobse bereits beschrieben hat, ist das erste Bit das Vorzeichen.
Und mit den restlichen drei Bit, kommt man eben nur noch bis 7
 

Tobse

Top Contributor
Bingo. @TE: Es geht hier inzwischen nichtmehr um Netzwerktechnik sondern um die Grundlagen von Binärer Arithmethik (sprich wir sind endlos Offtopic). Dieses Wissen wurde im WWW schon tausende male in Worte gefasst und wartet nur darauf, dass man es findet. Wenn ich deinen Wissensstand richtig einschätze wirst du bei einer Tour durch Tutorials zu Binärrechnung noch viele Aha-Erlebnisse haben (und die sind eine der besten Lernmethoden!).
 

devnator

Mitglied
Danke für die nette Hilfe von euch beiden :)
Lasse euch beide mal ein Top da :)
Ich hätte noch eine Frage wie funktionieren VarInts und was hat es da mit dem Shiften etc auf sich.
LG
 

Tobse

Top Contributor
Was ist ein VarInt? Es gibt in Java die Klassen BigInteger und BigDecimal, welche beliebig große Ganzzahlen/Fließkommazahlen darstellen und damit rechnen können (intern sind das Byte-Arrays).
 

InfectedBytes

Top Contributor
Danke für die nette Hilfe von euch beiden :)
Lasse euch beide mal ein Top da :)
Ich hätte noch eine Frage wie funktionieren VarInts und was hat es da mit dem Shiften etc auf sich.
LG
In Java gibt es keine VarInts.

Shiften bedeutet nur, dass du alle bits eine bestimmte Anzahl Stellen nach links oder rechts verschiebst:
Wenn du die Zahl 001011 zwei bit nach links schiebst, erhälst du eben 101100
 

devnator

Mitglied
Ja in Java direkt gibt es die nicht, aber man verwendet sie um Integer zu senden. Da es viel kürzer ist und weniger ressourcen zieht. Ich habe jetzt eine Methode aus dem Internet zum lesen und schreiben aber mir ist sie nicht ganz klar: public void writeVarInt(int i) { while ((i & -128) != 0) {
this.writeByte(i & 127 | 128);
i >>>= 7;
}

byteBuf.writeByte(i);
}


public int readVarInt() {
int i = 0;
int j = 0;

byte b0;

do {
b0 = byteBuf.readByte();
i |= (b0 & 127) << j++ * 7;
if (j > 5) {
throw new RuntimeException("VarInt too big");
}
} while ((b0 & 128) == 128);

return i;
}
 

InfectedBytes

Top Contributor
im Grunde ist das Ziel, immer möglichst wenig bits zu senden.
Wenn man nun z.b. die Zahl 64 verschicken möchte, ist es ja unnötig 4 Bytes zu verschicken, da diese Zahl auch in ein einzelnes Byte passt. Die Idee hinter den VarInts ist es nun, immer nur so wenig Bytes wie möglich zu schicken. Dabei gibt nun das vorderste Bit an, ob noch ein weiteres Byte gelesen werden soll oder nicht. Allerdings kann das vorderste somit nicht mehr für die Zahl benutzt werden und somit bleiben pro Byte nur noch 7 Bit für die Zahl übrig. Daraus folgt natürlich das du sehr große Zahlen und negative Zahlen nicht mehr in 4 Byte stecken kannst. Für diese Fällen werden dann halt 5 Byte gesendet. Da man aber davon ausgeht, das die meisten Zahlen eher klein sind, müssen meistens weniger als 4 Bytes gesendet werden.
Beispiel: 64 = 01000000
dies wird nun direkt als ein Byte mit 01000000 gesendet. Das vorderste Bit ist 0 => es muss kein weiteres Byte gelesen werden.
Beispiel 260 = 00000001 00000100
Dies wird als 00000010 10000100 gesendet, da das vorderste Bit von 00000100 benötigt wird, um anzuzeigen das noch ein Byte benötigt wird, daher wird 00000100 als 10000100. Die Bits des anderen Bytes müssen daher um eins weitergeschoben werden 00000001 wird also zu 00000010
 

InfectedBytes

Top Contributor
| = bitweises oder
& = bitweises und

Java:
public void writeVarInt(int i) { 
while ((i & -128) != 0) {
this.writeByte(i & 127 | 128);
i >>>= 7;
}
solange das 8. Bit ungleich null ist wird die schleife ausgeführt.
Mit i & 127 erhälst du nur noch die letzten 7 Bit des letzten Bytes.
Anschließend wird dies mit 128 "oder" verknüpft. Dadurch wird das 8. Bit auf 1 gesetzt.
Anschließend wird die Zahl um 7 Bit nach rechts verschoben.

Die andere Methode liest ein Byte ein.
Solange das vorderste bit 1 ist, wird ein weiteres byte eingelesen. und das bisherige ergebnis 7 bit nach links geschoben und das gelesene Byte angehängt.
Falls mehr als 5 Bytes eingelesen wurden, wird eine Exception geworfen, da ein VarInt logischerweise aus maximal 5 Byte besteht.
 
Zuletzt bearbeitet:

Neue Themen


Oben