PHP Problem mit Binärdaten

Hallo zusammen,

ich habe ein Problem mit der Bearbeitung von Binärdaten, ich habe jetzt schon 2 Stunden gegooglt in Tutorials, Wikis und Manuals aber leider komme ich nicht weiter, mir fehlt einfach der richtige Ansatz.

Das ist das erste mal das ich etwas mit Binärdaten mache.

Es geht um folgendes:
Ich sende via GET eine Anfrage an einen Server, zurück bekomme ich Binärdaten.

Ich frage das ganze wie fsocket an und mit fread wird die Serverantwort in eine Variable gespeichert, über eine Methode extrahier ich den Content/Body-Teil sodas ich den Binärteil alleine hab.

Ab jetzt weiß ich aber nicht mehr wie ich den Binärteil bearbeite,
gebe ich den Bodyteil im Browser aus wird zwar die 4 chars Zeichenfolge
ausgegeben aber ansonsten nur kryptische Zeichen.
(Ich hatte eigentlich mit nem haufen 0,1 gerechnet die ich dann nur noch zerschnippeln muss).

Ich habe es auch schon mit unpack versucht, aber ich steig da nicht so ganz hinter.

Ich bräuchte ja einen String mit 0 und 1 en den ich dann eifnahc nur gemäß der Spezifikation zerschneiden muss.


Wäre super wenn mir da mal jemand auf die Sprünge helfen könnte,

besten Dank!
 
Zuletzt bearbeitet:
(Ich hatte eigentlich mit nem haufen 0,1 gerechnet die ich dann nur noch zerschnippeln muss).
dein Denk-Fehler liegt darin, dass du gerne lesbare Zeichen vor dir hättest ("0" und "1"), jedoch bekommst du - da, wie du sagst, binary-Daten, chr(0) (00000000) und chr(1) (00000001) und ähnliches zurück.

Der Demo-Code:
PHP:
<?php
$binaryString = chr(0).chr(0).chr(1).chr(2);
$format = 'C'.(string)strlen($binaryString);
$str2 = unpack($format,$binaryString);
var_dump($str2);
gibt z.B. ein Array zurück, welches die einzelnen Nullen und Einsen beinhaltet.
 
Hey,

danke für deine Antwort also ich habe jetzt folgenden Code:
PHP:
$format = 'c'.$data["head"]["contentlength"];
$str2 = unpack($format,$data["body"]);

          echo"<pre>";
          var_dump($str2);
          echo"</pre>";

in $data["head"]["contentlength"] steckt die Antwort Contentlength vom Server, die ich via Get Abfrage bekommen habe.

In $data["body"] steht dann der Content drin, also die Binärdaten.

Wenn ich das ganze dann ausgebe erhalte ich folgendes:

PHP:
array(167) {
  [1]=>
  int(9)
  [2]=>
  int(0)
  [3]=>
  int(0)
  [4]=>
  int(0)
  [5]=>
  int(77)
  [6]=>
  int(83)
  [7]=>
  int(76)
  [8]=>
  int(71)
  [9]=>
  int(1)
  [10]=>
  int(25)
  [11]=>
  int(0)
  [12]=>
  int(0)
  [13]=>
  int(0)
  [14]=>
  int(-106)
  [15]=>
...u.s.w.
}

Also auch keine 0 oder 1 sondern schon konkrete Werte, und Minuswerte sind auch dabei, dass dürfte eigentlich gar nicht.

Mit der Ausgabe kann ich ja nicht mehr die einzelnen Bytes zerlegen und somit die Werte erhalten die ich brauche :(

Ich poste noch mal die PHP Schnippsel zur GET Abfrage und Zerlegung der Antwort in Head und Body:

Ich poste mal nur den relevanten Teil:

GET
PHP:
$connection=@fsockopen($this->host,$this->port);

fwrite($connection,'GET '.$uri.$paramstring." HTTP/1.1\r\nHost: ".$host."\r\nUser-Agent: ".$this->useragent."\r\n".$cookiestring.$authstring."Connection: close\r\n\r\n");
		$reply='';
		while (!feof($connection))
			{
				$reply.=@fread($connection,128);
			}
		fclose($connection);
		$data=$this->decodereply($reply);
		return $data;

decodereply
PHP:
private function decodereply($reply)
	{

		$headend=strpos($reply,"\r\n\r\n")+2;
		$head=substr($reply,0,$headend);
		$httpversion=substr($head,5,3);
		$contentlength='';
		$contentlengthstart=strpos($head,'Content-Length:');
		if ($contentlengthstart!=false)
			{
				$contentlengthstart+=16;
				$contentlengthend=strpos($head,"\r\n",$contentlengthstart);
				$contentlength=substr($head,$contentlengthstart,$contentlengthend-$contentlengthstart);
			}
		if ($httpversion=='1.0')
			{
				$datastart=$headend+2;
				$body=substr($reply,$datastart,strlen($reply)-$datastart);
			}
		elseif ($httpversion=='1.1')
			{
				$encoding='';
				$encodingstart=strpos($head,'Transfer-Encoding:');
				if ($encodingstart!=false)
					{
						$encodingstart+=19;
						$encodingend=strpos($head,"\r\n",$encodingstart);
						$encoding=substr($head,$encodingstart,$encodingend-$encodingstart);
					}
				if ($encoding=='chunked')
					{
						$datasizestart=$headend+2;
						$datasizeend=strpos($reply,"\r\n",$datasizestart);
						$datasize=hexdec(trim(substr($reply,$datasizestart,$datasizeend-$datasizestart)));
						$body='';
						while ($datasize>0)
							{
								$chunkstart=$datasizeend+2;
								$body.=substr($reply,$chunkstart,$datasize);
								$datasizestart=$chunkstart+$datasize+2;
								$datasizeend=strpos($reply,"\r\n",$datasizestart);
								$datasize=hexdec(trim(substr($reply,$datasizestart,$datasizeend-$datasizestart)));
							}
					}
				else
					{
						$datastart=$headend+2;
						$datasize=$contentlength;
						$body=substr($reply,$datastart,$datasize);
					}
			}
		$code=substr($head,9,3);
		$serverstart=strpos($head,'Server:')+8;
		$serverend=strpos($head,"\r\n",$serverstart);
		$server=substr($head,$serverstart,$serverend-$serverstart);
		$contenttype='';
		$contenttypestart=strpos($head,'Content-Type:');
		if ($contenttypestart!=false)
			{
				$contenttypestart+=14;
				$contenttypeend=strpos($head,"\r\n",$contenttypestart);
				$contenttype=substr($head,$contenttypestart,$contenttypeend-$contenttypestart);
			}
		$location='';
		$locationstart=strpos($head,'Location:');
		if ($locationstart!=false)
			{
				$locationstart+=10;
				$locationend=strpos($head,"\r\n",$locationstart);
				$location=substr($head,$locationstart,$locationend-$locationstart);
				$location_array=explode('?',$location);
				$parameters='';
				if (isset($location_array[1]))
					{
						$parameters=$location_array[1];
					}
				$location=array('uri'=>$location_array[0],'parameters'=>$parameters);
				if (empty($parameters))
					{
						unset($location['parameters']);
					}
			}
		$cookies=array();
		$cookiestart=strpos($head,'Set-Cookie:');
		while ($cookiestart!=false)
			{
				$cookiestart+=12;
				$cookieend=strpos($head,"\r\n",$cookiestart);
				$cookie=substr($head,$cookiestart,$cookieend-$cookiestart);
				$cookie_array=explode(';',$cookie);
				$expirydate='';
				$path='';
				for ($x=0;$x<count($cookie_array);$x++)
					{
						$cookie_array[$x]=explode("=",$cookie_array[$x]);
						if ($x==0)
							{
								$name=$cookie_array[$x][0];
								$value=$cookie_array[$x][1];
							}
						else
							{
								if (trim($cookie_array[$x][0])=='expires')
									{
										$expirydate=array('string'=>$cookie_array[$x][1],'timestamp'=>strtotime($cookie_array[$x][1]));
									}
								elseif (trim($cookie_array[$x][0])=='path')
									{
										$path=$cookie_array[$x][1];
									}
							}
					}
				$cookie=array('name'=>$name,'value'=>$value,'path'=>$path,'expirydate'=>$expirydate);
				if (empty($path))
					{
						unset($cookie['path']);
					}
				if (empty($expirydate))
					{
						unset($cookie['expirydate']);
					}
				$cookies[]=$cookie;
				$cookiestart=strpos($head,'Set-Cookie:',$cookieend);
			}
		$headdata=array('raw'=>$head,'httpversion'=>$httpversion,'code'=>$code,'server'=>$server,'contentlength'=>$contentlength,'contenttype'=>$contenttype,'location'=>$location,'cookies'=>$cookies);
		if ((empty($contentlength)) && ($contentlength!=0))
			{
				unset($headdata['contentlength']);
			}
		if (empty($contenttype))
			{
				unset($headdata['contenttype']);
			}
		if (empty($location))
			{
				unset($headdata['location']);
			}
		if (empty($cookies))
			{
				unset($headdata['cookies']);
			}
		$data=array('head'=>$headdata,'body'=>$body);
		return $data;
	}

Der Code stammt aus der httpconnection_class von Dennis Wronka


Freue mich über jede Hilfe/Tipp :)
Vielen Dank!
 
Du arbeitest da auf Byte-Ebene, dein Datenstrom aber auf Bit-Ebene. Du musst dir also aus dem Byte z.B. 71 die jeweiligen Bits herauspflücken und entsprechend deinem Protokoll interpretieren.

Dir schient es da an Grundlagen zu fehlen, also empfehle ich dir dich damit erstmal zu Beschäftigen. Weißt du z.B. das die 71, die du jetzt siehst in dem Format, in dem du es haben willst 1000111 wäre? Mir scheint als wäre dem nicht so.
 
Hey Thunderb0lt,

also die Grundlagen von Bit's und Bytes sind mir schon bewusst, auch das
71 Binär 1000111 ist :)

Das Arbeiten mit Binärdaten ist mir aber völlig fremd :/

Mir hilft auf jeden Fall schon mal deine Aussage das jeder Index im Array für die Summe des gesamten Byte steht. (Das war mir nicht klar)

Das hieße ich habe 167 Byte als Antwort bekommen, die ich jetzt gemäß meines Protokolls verarbeiten kann.

Es klappt also ;)

Das jeder INDEX ein BYTE ist war der entscheidene Hinweis den ich gebraucht habe.

Hab vielen vielen vielen vielen Dank dafür :)
 
Zuletzt bearbeitet:
zu deinem Problem mit den negativen Zahlen:
ein kleines 'c' steht für ein vorzeichenbehaftetes Zeichen, ein großes 'C' für vorzeichenloses Zeichen. Siehe dazu http://php.net/manual/de/function.pack.php

was vielleicht auch nicht ganz uninteressant für dich ist, sind die Bit-Operatoren und, wenn du einzelne Bits brauchst, natürlich decbin()

edit:
Beispiel: wir haben binär 01001010 vorliegen, das entspricht also dezimal der 74.

die ersten 6 Bit stehen für etwas bestimmtes und die letzten beiden stehen für was anderes.
PHP:
<?php
$byte = 74;            // 01001010
$val1 = $byte & 0x03;  // mit Bitmaske 00000011 ver-UNDen (alle Bits, bei denen die Bitmaske 0 ist, werden auch 0, alle Bits, wo die Bitmaske 1 ist, bleiben, wie sie sind)
$val2 = $byte >> 2;    // schiebt Bits 2 Stellen nach rechts und füllt links mit Nullen auf

echo $val1;            // 00000010 = 2
echo $val2;            // 00010010 = 18
 
Hi beavisbee,

danke für dein Hinweis,
das mit dem großen C hatte ich derweilen schon im Manual nachgelesen, klappt prima :)

decbin ist aber sehr interessant, kannte ich noch nicht, vielen liebe Dank !
 
Danke für das Beispiel,
das verstehe ich auch soweit.

Frage mich nur wofür das relevant ist, naja vielleicht erschließt es sich mir ja demnächst mal wenn ich mehr mit Binärdaten arbeite. :)
 
Zurück
Oben