# Networking



## devnator (28. Jun 2015)

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 (28. Jun 2015)

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 (29. Jun 2015)

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 (29. Jun 2015)

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 (29. Jun 2015)

InfectedBytes hat gesagt.:


> 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 (29. Jun 2015)

Ja aber wie genau macht das Java das er das auf 0 und 1 hinunter bricht ?


----------



## Tobse (29. Jun 2015)

Nochmals: Java macht das nicht. Das macht die Netzwerkkarte über Physikalische Schaltkreise. Diese Logik steckt dahinter (Binärsystem): https://www.youtube.com/watch?v=tgR2IGtP4tY


----------



## devnator (29. Jun 2015)

@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 ?


----------



## InfectedBytes (29. Jun 2015)

nein, aber wie du bereits gesagt hast, besteht ein int aus 4 Byte. und dementsprechend aus 32 Bit


----------



## Tobse (29. Jun 2015)

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:


```
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...


----------



## devnator (29. Jun 2015)

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


----------



## devnator (29. Jun 2015)

@Tobse


----------



## Tobse (29. Jun 2015)

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".


----------



## devnator (29. Jun 2015)

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


----------



## InfectedBytes (29. Jun 2015)

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 (29. Jun 2015)

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 (30. Jun 2015)

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 (30. Jun 2015)

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 (30. Jun 2015)

devnator hat gesagt.:


> 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 (30. Jun 2015)

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 (30. Jun 2015)

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


----------



## devnator (3. Jul 2015)

ok danke und könntest du noch mal explizit auf die  Methode eingehen also was ist | das & die methode erklären wäre super ^^


----------



## InfectedBytes (3. Jul 2015)

| = bitweises oder
& = bitweises und


```
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.


----------

