# Paket-Analysieren Byte-Streams



## ninaa (15. Jan 2013)

Hallo Forum,

ich habe ein Proxy geschrieben, der für jeden Client 2 Sockets zur Kommunikation mit einem Server öffnet.
ein socket zur Kommunikation der Client mit dem Proxy, einen Socket zur Kommnikation der Proxy mit dem Server.
ich versuche momentan Pakete, die ein Client schickt zu analysieren und an einen bzw. 2 Server weiterzuleiten. Das problem ist, dass ich die byte-streams lesen und weiterleiten, jedoch nicht analysieren kann. So funktioniert alles mit weiterleiten der Nachrichten, die Client und Server schicken.

```
byte[] buf=new byte[bufSize];
	    int count=-1;
		InputStream in=inSock.getInputStream();
		OutputStream out=outSock.getOutputStream();
	        while(((count=in.read(buf))>0) && !isInterrupted()) {
		    	out.write(buf,0,count);
}
```
Sobald ich anfange zu analysieren. z.B. mit :

```
while(((count=in.read(buf))>0) && !isInterrupted()) {
		    	out.write(buf,0,count); //zum Primary Server
                        if (buf[0] == 0x00){
                        out2.write(buf,0,count); //zum einen secondry Server
}
```
wird die erste Anfrage richtig weitergeleitet aber der zweite nicht.
hat jemand eine Ahnung woran es liegt? 
danke für eute Hilfe
Nina


----------



## SlaterB (16. Jan 2013)

am Code ist nichts falsches zu erkennen, 
hast du irgendwelche weiteren Informationen?
was bedeutet 'aber der zweite nicht' genau?

geht es um out und out2 oder eine zweite Übertragung?
was genau passiert bei der zweiten Übertragung, finde durch System.out.println()-Log-Ausgaben oder sonstige Mittel etwas über den Zustand des Proxys heraus, 
ist das Programm beendet, reagiert es gar nicht, bekommt es die Eingabe mit aber die Schleife wird nicht durchlaufen,
hängt es bei einem bestimmten Senden oder sonstiger Zeile, noch (am Ende) bei erster Übertragung oder zu Beginn der zweiten?

notfalls musst du zwischen jeder einzelne Programmzeile eine Ausgabe schreiben um so viel wie möglich herauszufinden WAS denn nun passiert zu jedem Zeitpunkt

etwas mehr Code zu out2, generell zur Annahme und Beendigung der Streams, Schleife usw. könnte womöglich helfen


----------



## ninaa (16. Jan 2013)

Hallo und danke dir für die Antwort.

ja das Problem ist, dass ich nicht weiß, wann der Buffer geleert wird. Ich habe angenommen, dass der Buffer zuerst voll und dann geschickt wird.
Ich kann erfolgreich den Buffer an ersten outputstream out1 legen. (der Server bekommt die Anfrage) sobald ich aber versuche etwas anderes damit zu machen (z.B. das gleiche buffer nachdem ich es an out1 gelegt habe, auf den zweiten outputstream out2 zu legen) , bleib das programm an while-schleife hängen und der client kann schicken, was er will, bekommt er gar nichts zurück (der Proxy auch nichts). Somit kann die erste Anfrage geschickt werden, bei der zweiten Anfrage bleibt das Programm hängen.

Ich suche nach einer Möglichkeit, die buffers bevor es an server geschickt wird, in einem Vector einzutragen. Ich denke somit kann ich doch alle nachrichten, die vom Client geschickt werden in einem Vector haben und dann sie analysieren kann.


----------



## SlaterB (16. Jan 2013)

> Ich suche nach einer Möglichkeit, die buffers bevor es an server geschickt wird, in einem Vector einzutragen.

da gibts nicht viel zu suchen, einfach machen, wobei du aufpassen musst dass du nicht ein und dasselbe Array mehrfach ablegst,
wenn sich der Inhalt ändert hast du am Ende nur viele Referenzen auf den letzten Stand, 
Zwischenergebnisse kopieren

auf den zweiten OutputStream zu verzichten und die Daten irgendwie zwischenzuspeichern ist eine gute Idee der Variantion,
die manche Probleme umgehen kann, ohne dass man genau weiß woran es liegt,

ansonsten gilt alles vorherige: herausfinden was los ist, evtl. mehr Code posten


----------



## ninaa (16. Jan 2013)

wie kann ich das machen, ohne sie mehrfach zu speichern? was liegt auf einem Buffer? ich denke nicht wenn der Client eine Anfrage schicket und zweite und dritte noch... wie kann ich die Anfragen auseinander halten? oder schickt der Client die erste Anfrage und wartet bis der Buffer wieder frei gegeben wird

der Proxy weiß, wie die Pakete aufgebaut sind. Der buffer, wie ich es verstehe, kann mehrere Packete enthalten. gibt es irgendeine Methode, die Pakete auseinander zu halten. Sie fangen mit einem Code im Header an, der kann aber auch als Nutzdaten vorkommen. Soll ich komplette packetanalyse machen, um festzustellen, welches paket, wo anfängt? oder geht es auch angenehmer??


----------



## SlaterB (16. Jan 2013)

> wie kann ich das machen, ohne sie mehrfach zu speichern?

ein einfacher erster Weg wäre, nach jedem Lesen ein neues byte[] zu erstellen,
oder nicht die byte[] speichern sondern diese in eine größere Struktur schreiben, z.B. ByteArrayOutputStream,
bisschen ausprobieren gehört dazu

> wie kann ich die Anfragen auseinander halten? 
das ist in der Tat ein allgemein interessantes Problem für deine Analyse, welche Bytes bedeuten was,
schon der Empfänger selber steht vor dieser Frage,

eine Universallösung kann ich nicht nennen, Protokoll ist normalerweise das Stichwort, wissen was gesendet wird,
am Anfang z.B. die Anzahl der folgenden Bytes usw.,
für einen Zwischen-Proxy freilich deutlich weniger möglich, weiß normalerweise weniger

vielleicht auf Pausen zwischen Übertragungen achten usw., letzlich kann es aber unmöglich sein und das ist auch gut so,
ein beliebiger Abhörer an einem Kabel von konstant 100 verschlüsselten Bytes pro Sekunde soll eben genau nichts ablesen können

für dein bisheriges Problem müsste das aber unerheblich sein,
die Daten kommen und gehen, welche Bedingung du für out2 oder sonstige Aktionen stellst haben nichts mit der Blockierung zu tun oder wenn doch dann gut, dann endlich mal ein Hinweis


----------



## ninaa (16. Jan 2013)

vielen lieben Dank ,

ich denke, da ich auch die Nachrichtenaufbau kenne, und sie unverschlüsselt geschickt werden, muss ich doch komplette analyse machen. somit wird der Proxy sehr überlastet werden. mir bleibt aber sonst keine andere möglichkeit. die Nachrichten enthalten keine Information, wo das Paket endet.  im header stehet aber alles, wie groß sie sind.


----------



## ninaa (16. Jan 2013)

wie kann ich ByteArrayOutputStream nutzen? kann ich den Stream von Socket.getOutputStream in einem Object von der class ByteArrayOutputStream speichern?


----------



## SlaterB (16. Jan 2013)

so wie du in parallel in out2 schreibst, welchen du glaube ich noch nicht näher erklärt hast, 
kannst du in einen angelegten ByteArrayOutputStream schreiben, 
dort sammeln sich die (fast beliebig vielen) Bytes im Arbeitsspeicher statt wer weiß wo hinzugehen

mit Pech dann nicht viel anders als bisher, wieder blockierend oder was immer das unbekannte Problem ist,
wenn aber out2 ins Netzwerk geht, dann wäre ein ByteArrayOutputStream ein bisschen was anderes, halber Weg zu einem Vector, ein kopiertes Array in einer Variablen und ähnlich einfachen Java-Vorgängen, denen man normalerweise keine Probleme zuschreibt


----------



## ninaa (16. Jan 2013)

also ou2 schickt das gleiche streams wie out1. das out1 geht in die richtung Primaryserver und out2 soll in richtung secondary server gehen.  aber wie gesagt, das funktioniert nicht mit dem was ich als code geschickt habe. auch wenn ich direkt an beiden server schicke, funktioniert nicht und bleibt hängen:

```
while(((count=in.read(buf))>0)&&!isInterrupted()) {
		    	out.write(buf,0,count);
                        out2.write(buf,0,count);
		    }
```
wenn ich nun:

```
ByteArrayOutputStream IOforReplicationStream = new ByteArrayOutputStream();
while(((count=in.read(buf))>0)&&!isInterrupted()) {
                        IOforReplicationStream = ???
		    	out.write(buf,0,count);
                        //out2.write(buf,0,count);
		    }
```
wie kann ich den Buffer buf auch in  IOforReplicationStream schreiben? wie kann ich den nächsten vom client kommende Buffer an  IOforReplicationStream hängen? damit ich nachher weiß, welche pakete er an primary geschickt hat und das gleiche dann an secondary schicken kann?


----------



## SlaterB (16. Jan 2013)

Variablen klein schreiben, ansonsten ist wie gesagt IOforReplicationStream ein Stream wie jeder andere,

statt
> out2.write(buf,0,count);
also z.B.
> IOforReplicationStream.write(buf,0,count);

am Ende kann man sich die Bytes abholen

------

zur Blockierung immer alles mögliche testen,
ist es schon schlimm wenn du nur out2 deklarierst, aber nichts schreibst?

ist es schlimm wenn du ganz unabhängig von inSock am Anfang etwas in out2 schreibst oder oder
vieles könnte man testen

was genau die Reaktion ist, ist sowieso noch unklar, 
anscheinend ist inSock ja länger offen, bewegt sich der Code die ganze Zeit nur in der Schleife?
was genau verstehst du unter dem Problem, sendest du etwas und geht normalerweise die Schleife in einen neuen Durchlauf,
aber dies passiert nun nicht mehr?
setze wie gesagt Log-Ausgaben, z.B. vor und nach dem out2.write()-Aufruf in der Schleife, wird dieses write() ausgeführt, also auch beendet, oder blockiert es?

wird am 'secondary server' aus out2 gelesen? wenn nicht kann das wohl Probleme machen, dann wartet womöglich der Sender,
ergo wird out2.write() nicht fertig,

wiederum gegebenfalls zu testen in eigenen Programm, Server, Client, Verbindung aufmachen, Server akzeptiert aber macht danach nicht wirklich was, keine in.read()-Schleife, Client sendet unaufhörlich,
was passiert?
sende bis zu hunderte MB, geht das? sind die am Ende auch alle da, wenn der Server nach festgelegter Pause von 5 Min. auf einmal doch liest?


----------



## ninaa (16. Jan 2013)

IOforReplicationStream.write(buf,0,count);  habe ich in code geschrieben. Nun habe ich die Frage: 

```
while(((count=in.read(buf))>0)&&!isInterrupted()) {
		    	//streams copy
		    	//streamList.add(buf);
                        IOforReplicationStream.write(buf,0,count);
		        out.write(buf,0,count);
 }
```
client schickt eine Nachricht. Buffer wird voll und dann wird als ein Stream zum Proxy(Server) geschickt. noch davor schreibt er auch in IOforReplicationStream. der Buffer wird schon wieder voll mit der nächsten Anfrage (oder vielleicht mit drei weitere Anfragen-weil die Größe des Pakets sind unterschiedlich),... wird dann  schon wider in IOforReplicationStream schreiben. was wird nun gemacht? hängt er die nächste Streams am ende der IOforReplicationStream? oder überschreibt er IOforReplicationStream??? Ich bräuchte die komplette Client-nachrichten. Ich kann auch erst nachdem ich das Paket analysiert habe, feststellen wie große es ist.


----------



## SlaterB (16. Jan 2013)

soviel Misstrauen, warum sollte ByteArrayOutputStream in diesem Fall nicht einfach das machen, was sinnvoll ist?
die wenigen Zeilen in der API-Beschreibung genügen wohl völlig


> This class implements an output stream in which the data is written into a byte array. The buffer automatically grows as data is written to it. The data can be retrieved using toByteArray() and toString().
> 
> Closing a ByteArrayOutputStream has no effect. The methods in this class can be called after the stream has been closed without generating an IOException.


ByteArrayOutputStream (Java Platform SE 7 )

Ausprobieren mit Dummydaten (einzelne Bytes oder Array der Größe 3) ist auch nie verboten



------

zu meiner Idee des blockierenden out2:
tritt die Blockierung immer nach einer bestimmten byte-Menge auf?
z.B. bei der ersten Nachricht wenn diese 5000 Bytes groß ist,
bei 500 Byte dagegen erst bei der ~10. Nachricht (beliebige Beispielzahlen)

blockiert out2 auch, wenn dann völlig unabhängig von inSock gleich die nötige Menge an Bytes in out2 geschrieben wird?
mit inSock muss das alles nichts zu tun haben, out2 kann einfach so schlecht sein


----------

