Etter å ha "fiklet" litt med Qt-Creator og brukt C++ for første gang på lenge så må jeg ærlig innrømme og si det at det er mange fine klasser. Og en av klassene er veldig greie å venne seg til er QString. Med denne klassen kan man gjøre veldig mye med strenger som ellers ville ha knotet med. Det er vel egentlig bare 2 måter/metoder jeg har lyst til å skrive litt om. Dvs jeg vil sammenlikne 2 metoder for å illustrere lettvintheten med å bruke en klasse som QString. Jeg har ikke satt meg inn i std::string så veldig så jeg vet ikke hva den klassen er kapabel til, men det spiller ingen rolle. 

Nå har jeg gjennomført et mindre prosjekt som faktisk gjør noe nyttig, for å prøve å sette meg litt inn i dette(som jeg nevnte i forrige artikkel om qt). I denne applikasjonen så har jeg brukt Qt-Creator/C++ til å lage en klient som skal koble seg til itree-serveren vha TCP/socket tilkopling. Har som sagt tidligere, laget en C-versjon(kjøres i bakgrunnen) og en PHP-versjon(som også har en del fine funksjoner for strukturering av dataen). I denne versjonen(C++ vha Qt), så er det ikke noe nytt. Grafisk grensesnitt er vel det eneste nye. Så langt iallefall. Man kan også velge hvilket tre man vil kople seg på. Her er iallefall et skjermbilde:

Ja nå har jeg lagt til det siste touchet på en måte på klassen itreeclient. Ikke så store forandringer fra sist. Det jeg har gjort er å fjerne funksjonen itreeSendRq(...) og så initiailsere alt i __construct(...), med de nødvendige parameterne. Det var egentlig det jeg hadde tenkt på fra begynnelsen av men så er det en bug som jeg ikke klarte å finne. Men "bøggen" hvis man kan kalle det det går på at jeg ikke kan sende noen requests lokalt på maskina. Hele daemonen blir stoppet. Den burde forsvidt takle NULL-verdier eller hva det nå enn er den ikke takler men tror problemet ligger i det at den ikke får de parameterne den skal ha når jeg bruker funksjonen "fsockopen( )" lokalt. Skal se på det senere.

Iallefall: De fleste funksjoner og data er blitt private. Det er bare en måte å få data på, og det er gjennom medlems-funksjonen getData( ). Det er jo greit. Har planer om la den få en eller flere parametere slik at du kan få dataen ut i forskjellige formater. F.eks:

  1. uformatert(som en lang streng)
  2. formatert(streng i 2 dimensjoner)
  3. skrive ut i tabell med css-klasse som en parameter

Disse 3 variantene er mest relevant. Kan ikke se akkurat her og nå at noe annet skal være relevant.

Iallefall. Her er klassen: Nyeste variant:

 

<?php
/**
 * Documentation, License etc.
 *
 * @package itreeclient
 */

error_reporting(E_ALL);
function MAKEULONG($a, $b, $c, $d)
{
	return (($a<<24) | ($b<<16) | ($c<<8) | $d);
}
function BYTE32($dw)
{
	return (($dw & 0xFF000000)>>24);
}
function BYTE24($dw)
{
	return (($dw & 0x00FF0000)>>16);
}
function BYTE16($dw)
{
	return (($dw & 0x0000FF00)>>8);
}
function BYTE8($dw)
{
	return ($dw & 0x000000FF);
}


class itreeClient
{
  //user input
  private $request;
  //string sent to server as a request
  private $data_request;
  //name of the data-tree we want to search.
  private $data_tree;
  private $received_data;
  private $hsocket;
  
  private function writeIData()
  {
	  $CMDIT_DATA_GET = 0x01;
	  $DT_STRING = 0x01;
	  $index = 0;
	  
	  $buf_size = strlen($this->data_request)+1;
	  //pack data into binary/hex-values."C7"=>unsigned char		
	  $data = pack("C7",$CMDIT_DATA_GET, $DT_STRING, BYTE32($buf_size),BYTE24($buf_size),BYTE16($buf_size),BYTE8($buf_size),$index);

	  $n = fwrite($this->hsocket, $data);
	  if(!$n)
	  {
		  echo "First write failed(writeIData). Data: ".$data."...var_dump: ".var_dump($n)."\n";
		  return 0;
	  }
	  else 
	  { //echo "writeIData(data_request):".$this->data_request."\n"; 
		  $str = $this->data_request;
		  $n = fwrite($this->hsocket, $str);
		  if(!$n)
		  {
			  echo "Second write failed(writeIData). Data: $this->data_request...var_dump: ".var_dump($n)."\n";
			  return 0;
		  }
	  }
	  return 1;
  }
  private function readIData()
  {
	  $n = fread($this->hsocket, 7);
	  if(!$n)
	  {
		  "Reading of header-data failed...exiting: var_dump: ".var_dump($n)."\n";
		  return NULL;
	  }
	  else
	  {
		  $pd = unpack('C7', $n);//unpack the header-package	
		  //get first value
		  $response_type = $pd[1];
		  //get second value
		  $data_type = $pd[2];
		  //get ulong value-parts
		  $data_index = $pd[7];
		  $buf_size = MAKEULONG($pd[3],$pd[4],$pd[5],$pd[6]);
		  $itree_data = fread($this->hsocket, $buf_size+4);
		  
		  if(!$itree_data)
		  {
			  echo "Second read failed in readIData...buf_size: $buf_size, var_dump(n): ".var_dump($itree_data)." \n";
			  return NULL;
		  }
		  
	  }//for some reason I'm getting 1 byte more than I ask for at the begining of the data-buffer.
	  //remove it for now..
	  return substr_replace($itree_data, NULL, 0, 1);	
  }
  //constructor..setting most important stuff.
  function __construct($ip, $port, $searchterm=NULL)
  {
    $this->data_tree = "then";
    $this->request = $searchterm;
    if($this->request === NULL)
    {
	    echo "Error: No point in sending NULL. Exiting script.";
	    return NULL;
    }
    $this->data_request = $this->data_tree."&".$this->request."\0";
//    echo $this->data_request;
    $this->hsocket = fsockopen($ip, $port, $errno, $errstr);
    if($this->hsocket === FALSE)
    {
	    echo "Opening socket failed.\n";
	    echo "errno: $errno\n";
	    echo "error_str: $errstr\nExiting with return-value 1";
	    return NULL;
    }	
    if($this->writeIData() === NULL)
    {
	    echo "writeIData returned NULL...exiting";
	    stream_socket_shutdown($this->hsocket, STREAM_SHUT_RDWR);
	    return NULL;
    }
    $this->received_data = $this->readIData();
    if($this->received_data === NULL)
    {
	    echo "readIData returned NULL...exiting";
	    stream_socket_shutdown($this->hsocket, STREAM_SHUT_RDWR);
	    return NULL;
    }
    //echo "Received data:\n".$received_data."\n";
    stream_socket_shutdown($this->hsocket, STREAM_SHUT_RDWR);
  }
 
  public function GetData()
  {
    return $this->received_data;
  }
};

Og her er et eksempel brukt i index.php på nettsiden på hvordan man kan bruke det:

 

include_once("itreeclient.php");
$obj = new itreeClient('84.xx.xx.xx', $portnumber,$searchterm);
$rdata = $obj->GetData();

 

Er det en ting jeg aldri har gjort så er det å lage et grafisk grensesnitt til et program i Linux. Har stort sett bare laget web-skript/applikasjoner eller terminal-applikasjoner. Så da tenkte jeg at jeg skulle utforske dette. Et grensesnitt som skal være godt utarbeidet er Qt

Jeg fortsetter og fortsetter med iTree. Tror grunnen jeg gjør det er fordi det er et noe man kan jobbe med. Det inneholder alt nesten. Jeg bestemte meg iallefall for å ordne litt på kildekoden til php-klient-delen. Dvs lage en egen klasse. Jobbe litt OO. Være litt trendy...og ryddig ikke minst. Det har jeg ikke vært på mange år. Ryddig....har iallefall ikke skrevet OO på ei stund. Det er sikkert 10 år siden. Alt er 10 år siden om dagen så jeg lyver sikkert. 6 år kanskje. Så da må man jo ha en formening om hvorfor jeg skal lage en klasse. 

  1. Ryddig kode
  2. sikkerhet

Det er jo ikke dumt. Poenget er jo at man skal lage et objekt, gjøre en query og få et svar. Ikke skrive en hel masse tilleggsting som kanskje endrer variabler eller mister oversikt over hva man kan gjøre.

Mitt mål med dette er at man skal initiere objektet og så hente data. Det er alt.

Jeg gjorde det. Men fikk et annet problem som jeg ikke helt har funnet ut hva er. Koden fungerer når det er lagt til på nettsiden men jeg kan ikke kjøreskriptet lokalt på terminalen min på arbeids-stasjonen. Merkelige ting dette. Her er klassen iallefall:

 

class itreeClient
{
  //user input
  private $request;
  //string sent to server as a request
  public $data_request;
  //name of the data-tree we want to search.
  private $data_tree;
  public $received_data;
  private $hsocket;
  
  private function writeIData()
  {
	  $CMDIT_DATA_GET = 0x01;
	  $DT_STRING = 0x01;
	  $index = 0;
	  
	  $buf_size = strlen($this->data_request)+1;
	  //pack data into binary/hex-values."C7"=>unsigned char		
	  $data = pack("C7",$CMDIT_DATA_GET, $DT_STRING, BYTE32($buf_size),BYTE24($buf_size),BYTE16($buf_size),BYTE8($buf_size),$index);

	  $n = fwrite($this->hsocket, $data);
	  if(!$n)
	  {
		  echo "First write failed(writeIData). Data: ".$data."...var_dump: ".var_dump($n)."\n";
		  return 0;
	  }
	  else 
	  { echo "writeIData(data_request):".$this->data_request."\n"; 
		  $str = $this->data_request;
		  $n = fwrite($this->hsocket, $str);
		  if(!$n)
		  {
			  echo "Second write failed(writeIData). Data: $this->data_request...var_dump: ".var_dump($n)."\n";
			  return 0;
		  }
	  }
	  return 1;
  }
  private function readIData()
  {
	  $n = fread($this->hsocket, 7);
	  if(!$n)
	  {
		  "Reading of header-data failed...exiting: var_dump: ".var_dump($n)."\n";
		  return NULL;
	  }
	  else
	  {
		  $pd = unpack('C7', $n);//unpack the header-package	
		  //get first value
		  $response_type = $pd[1];
		  //get second value
		  $data_type = $pd[2];
		  //get ulong value-parts
		  $data_index = $pd[7];
		  $buf_size = MAKEULONG($pd[3],$pd[4],$pd[5],$pd[6]);
		  $itree_data = fread($this->hsocket, $buf_size+4);
		  
		  if(!$itree_data)
		  {
			  echo "Second read failed in readIData...buf_size: $buf_size, var_dump(n): ".var_dump($itree_data)." \n";
			  return NULL;
		  }
		  
	  }//for some reason I'm getting 1 byte more than I ask for at the begining of the data-buffer.
	  //remove it for now..
	  return substr_replace($itree_data, NULL, 0, 1);	
  }
  //constructor..setting most important stuff.
  function __construct(){ }
  ////send request for data
  public function itreeSendRq($ip, $port, $searchterm=NULL)
  {
    $this->data_tree = "then";
    $this->request = $searchterm;
    if($this->request === NULL)
    {
	    echo "Error: No point in sending NULL. Exiting script.";
	    return NULL;
    }
    $this->data_request = $this->data_tree."&".$this->request."\0";
    echo $this->data_request;
    $this->hsocket = fsockopen($ip, $port, $errno, $errstr);
    if($this->hsocket === FALSE)
    {
	    echo "Opening socket failed.\n";
	    echo "errno: $errno\n";
	    echo "error_str: $errstr\nExiting with return-value 1";
	    return NULL;
    }	
    if($this->writeIData() === NULL)
    {
	    echo "writeIData returned NULL...exiting";
	    stream_socket_shutdown($this->hsocket, STREAM_SHUT_RDWR);
	    return NULL;
    }
    $this->received_data = $this->readIData();
    if($this->received_data === NULL)
    {
	    echo "readIData returned NULL...exiting";
	    stream_socket_shutdown($this->hsocket, STREAM_SHUT_RDWR);
	    return NULL;
    }
    //echo "Received data:\n".$received_data."\n";
    stream_socket_shutdown($this->hsocket, STREAM_SHUT_RDWR);
  }
  public function GetData()
  {
    return $this->received_data;
  }
};

 

Noen variabler har blitt public, fordi jeg skulle teste og se om det hadde noe med de problemene jeg støtte borti. Det hadde ikke det. De skal være private. Som dere ser så er alle funksjoner bortsett fra GetData private. Dette har med sikkerhet å gjøre. Eneste man skal kunne gjøre med klassen er å hente data. Klassen kopler til serveren. Gjør en request og sender svar tilbake til brukeren.

Subcategories

Småprat om alt innen programmering

Artikler rundt om og men datamaskiner.