Vanuit php een 4 byte's lange integer versturen?

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik probeer een php client te bouwen voor de welbekende (?) nzbqueued server.
De server vereist dat commando's in een 4 byte's lange integer worden verstuurd. Een simpele "long integer" dus, zoals veel programmeertalen dat noemen

Dit levert natuurlijk problemen op, daar je in php niet zelf je type variabele kunt opgeven. Als ik een getal toeken aan een variabele in php, dan is die variabele natuurlijk nooit standaard 4 bytes, maar meestal twee, tenminste volgens strlen()

Ik heb al geprobeerd om het getal aan te vullen met nullen aan de voorkant, aan de achterkant, maar het lukt niet. Het grootste succes tot nu toe daarmee bereikt is dat ik de server heb laten crashen. |:(

Op google heb ik wel een paar referenties gevonden naar een functie "str2long" maar die kent mijn php niet :(

Heeft iemand ook maar enig idee hoe ik een long integer via php kan versturen?

Alvast bedankt.

Acties:
  • 0 Henk 'm!

  • Osiris
  • Registratie: Januari 2000
  • Niet online
Je hebt het nu 2x over een functie met "str" oftewel string. Daardoor zal PHP jouw integertje converten naar een string, omdat die functies geen integers als input pakken.. Daarom denk ik dat 't je ook niet zal gaan lukken.

Anywayz, kun je die integers niet gewoon omzetten naar binary ofzo? En dan 32 bits sturen?

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik converteer helemaal niets naar string. Ik heb alleen maar met strlen gekeken naar de lengte van een ingesteld getal. Dat bleek 2 te zijn, en dat werkt dus niet.

Ik heb dus gewoon om te kijken het volgende gedaan:
code:
1
2
$test_int = 0016;
echo strlen($test_int);


En daar komt dus 2 uit.

En dat converteren naar binary klinkt leuk. Maar nogmaals, ik krijg het dus niet voor elkaar om een variabele in het gewenste formaat te krijgen. Hoe ik het dan in godsnaam moet gaan redden om het zooitje naar binary te zetten is me dus een nog groter raadsel.

Acties:
  • 0 Henk 'm!

  • DizzyWeb
  • Registratie: Februari 2001
  • Laatst online: 05-09 14:30

DizzyWeb

Ondertiteld

Vergis ik me of is 0016 gewoon 16 en daarmee 2 bytes en niet 4?

Acties:
  • 0 Henk 'm!

  • pachacuti
  • Registratie: Januari 2002
  • Laatst online: 14-09 12:40
Als je van 16 0016 wil maken kan dat toch simpel met

code:
1
$value = sprintf("%04s",$value)

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Inderdaad. 16 is twee bytes. De server verwacht alleen 4 bytes (long integer) anders werkt 't niet, en blijft ie gewoon stug wachten op de andere twee bytes. Of, nog beter, twee commando's worden samengevoegd tot 1, want twee keer twee bytes is dan natuurlijk 4. Maar dan klopt er van de commando's natuurlijk ook niets meer. 8)7

Acties:
  • 0 Henk 'm!

  • Osiris
  • Registratie: Januari 2000
  • Niet online
OK, laat ik het even duidelijker uitleggen :)

Men surfe naar http://www.php.net/strlen voor uitleg over de functie strlen.. Men leest daar: int strlen ( string string )
Daaruit blijkt dat de functie een string als input neemt en een integer als output geeft. Zodra jij $random-variabele in de functie strlen invoert, zal PHP deze automatisch converten naar een string. Die voorgaande nullen van 0016 worden sowieso gestript, dus je houd over: "16". Dat is dus een string die uit 2 characters bestaat (namelijk een "1" en een "6") en dus zul je "2" als output krijgen :) Dit heeft dus geen moer te maken met hoeveel bytes je integer is.

Verder is 't niet zo moeilijk om een integer om te zetten naar binair: decbin-functie kan handig zijn. Je maakt er een string van vol met eentjes en nulletjes. Vervolgens doe je een strlen op die string van eentjes en nulletjes en je zorgt ervoor dat er 32-$lengtevanstr aan nulletjes voor komt te staan. En vervolgens kun je die strings in substrings van 8 chars knippen en vervolgens 4 losse bytes maken met decbin(). En die zou je bijv weer kunnen outputten mbv chr() ofzo.

Acties:
  • 0 Henk 'm!

  • DizzyWeb
  • Registratie: Februari 2001
  • Laatst online: 05-09 14:30

DizzyWeb

Ondertiteld

pachacuti schreef op woensdag 02 maart 2005 @ 23:53:
Als je van 16 0016 wil maken kan dat toch simpel met

code:
1
$value = sprintf("%04s",$value)
Dan maak je er alleen een string van en geen longint.

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Het aantal posities dat een integer inneemt in decimale tekens heeft niets te maken met hoeveel bits/bytes deze in het geheugen inneemt. Een normale integer is meestal 16 bits, dus 2 bytes lang. Hierin kun je getallen opslaan tussen de 0 en de 216 - 1.

Wellicht kun je proberen de betreffende integer als hex in te voeren. Een hexcode van 4 tekens lang is altijd 4 bytes. Ik weet alleen niet hoe dat in PHP werkt, maar aangezien PHP sterk op C lijkt, zal het waarschijnlijk zoiets zijn:
PHP:
1
$var = 0x0010; // 16 in decimale notatie


edit:
Of wat Osiris zegt. :P

[ Voor 4% gewijzigd door NMe op 02-03-2005 23:57 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
DizzyWeb schreef op woensdag 02 maart 2005 @ 23:55:
[...]

Dan maak je er alleen een string van en geen longint.
Inderdaad. Dat is het hele probleem.

Daarnaast moet de applicatie op meerdere besturingssystemen draaien. Bijvoorbeeld Mac, Linux, BSD, etc (gelukkig geen windows). En die hebben dan weer verschillende formaten voor long integers. Big Endian, en nog meer van die grappen. Als ik dus het hele zooitje zo maak dat het werkt op mijn linux systeem, dan werkt dat natuurlijk nooit op de mac.

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Verwijderd schreef op donderdag 03 maart 2005 @ 00:00:
Als ik dus het hele zooitje zo maak dat het werkt op mijn linux systeem, dan werkt dat natuurlijk nooit op de mac.
Natuurlijk? Je kan er bij de meeste systemen wel vanuit gaan dat een integer 16-bits is, en een long integer 32. Ik heb nooit voor de Mac geprogrammeerd, maar die is toch ook gebouwd op een 32-bits achitectuur, net als een gewone pc?

Verder: kun je wat met het verhaal van Osiris, of met dat van mij?

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Radiant
  • Registratie: Juli 2003
  • Niet online

Radiant

Certified MS Bob Administrator

http://nl2.php.net/pack
Misschien kan je daar wat mee, kan je ook automatisch laten uitzoeken of je machine little of big endian gebruikt.

Acties:
  • 0 Henk 'm!

  • pelican
  • Registratie: Juni 2001
  • Niet online

pelican

 

Als je iets verstuurt van een big-endian systeem naar een little-endian systeem, zorgt php (of ergens anders) er dan niet voor dat het juist wordt omgezet?

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Het gaat niet om het aantal bits, maar om de indeling van de bits.

De server is geschreven in C++.Nou is het zo dat, ondanks het feit dat C in theorie platform-onafhankelijk moet zijn, de indeling van de bits voor integere waarden verschilt. Als ik dus met de hand zo een variabele opbouw en de bitjes mooi plaats, werkt dat dus niet voor alle platformen.

Bij de gewone client werkt dat allemaal wel, omdat die namelijk ook gewoon in C++ geschreven is, en dus altijd dezelfde indeling heeft (want met dezelfde compiler wordt gebouwd).

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Radiant schreef op donderdag 03 maart 2005 @ 00:04:
http://nl2.php.net/pack
Misschien kan je daar wat mee, kan je ook automatisch laten uitzoeken of je machine little of big endian gebruikt.
Zo op het eerste gezicht is dat PRECIES wat ik nodig heb.
:)

* gaat snel even testen *

Acties:
  • 0 Henk 'm!

Verwijderd

-NMe- schreef op donderdag 03 maart 2005 @ 00:04:
Natuurlijk? Je kan er bij de meeste systemen wel vanuit gaan dat een integer 16-bits is, en een long integer 32. Ik heb nooit voor de Mac geprogrammeerd, maar die is toch ook gebouwd op een 32-bits achitectuur, net als een gewone pc?

Verder: kun je wat met het verhaal van Osiris, of met dat van mij?
wat de neuk? je kunt er vanuit gaan dat op de meeste systemen een int 32 bits is, de meeste huis tuin en keuken processoren zijn dat ook. Op een 64 bit proc is een int 64 bit.

Acties:
  • 0 Henk 'm!

  • mrFoce
  • Registratie: Augustus 2004
  • Laatst online: 09-09 17:18
waarvoor doe je niet gewoon bv 1161 en dan laat je de 'server' gewoon de middelste 2 getallen eruit filteren ( 1**1 -> 1 is om op te vullen )

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
gideon82 schreef op donderdag 03 maart 2005 @ 00:21:
waarvoor doe je niet gewoon bv 1161 en dan laat je de 'server' gewoon de middelste 2 getallen eruit filteren ( 1**1 -> 1 is om op te vullen )
Hier begrijp ik dus helemaal niets van. Ik heb de server niet geschreven. En ik geloof niet dat de server zo happig is om ook maar enige filtering toe te passen. Dan crasht ie liever. ;)

Acties:
  • 0 Henk 'm!

  • Radiant
  • Registratie: Juli 2003
  • Niet online

Radiant

Certified MS Bob Administrator

gideon82 schreef op donderdag 03 maart 2005 @ 00:21:
waarvoor doe je niet gewoon bv 1161 en dan laat je de 'server' gewoon de middelste 2 getallen eruit filteren ( 1**1 -> 1 is om op te vullen )
Dan kan hij net zo goed gewoon een unsigned char (byte, wat je het ook wil noemen) gebruiken :?
Maar het gaat hier dacht ik om een bestaande server applicatie, niet iets wat hij zelf geschreven heeft.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Osiris schreef op woensdag 02 maart 2005 @ 23:55:
Verder is 't niet zo moeilijk om een integer om te zetten naar binair: decbin-functie kan handig zijn. Je maakt er een string van vol met eentjes en nulletjes. Vervolgens doe je een strlen op die string van eentjes en nulletjes en je zorgt ervoor dat er 32-$lengtevanstr aan nulletjes voor komt te staan. En vervolgens kun je die strings in substrings van 8 chars knippen en vervolgens 4 losse bytes maken met decbin(). En die zou je bijv weer kunnen outputten mbv chr() ofzo.
Ik vind dit maar een omslachtige methode :)
PHP:
1
2
3
4
5
6
$val = 0x12345678;
$str = chr ($val & 0xff) .
       chr (($val >> 8) & 0xff) .
       chr (($val >> 16) & 0xff) .
       chr (($val >> 24) & 0xff);
fwrite ($file, $str, 4);


Voor big-endian even de string omdraaien. En niet vergeten de stream als binary te openen ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

-NMe- schreef op donderdag 03 maart 2005 @ 00:04:
[...]

Natuurlijk? Je kan er bij de meeste systemen wel vanuit gaan dat een integer 16-bits is, en een long integer 32. Ik heb nooit voor de Mac geprogrammeerd, maar die is toch ook gebouwd op een 32-bits achitectuur, net als een gewone pc?
Het kleinste adresseerbare element is meestal de byte, en dus hangt het er maar net vanaf in welke volgorde die 4 bytes van een int worden weggeschreven. Intel doet met z'n x86 eerst de least significant byte (lsb), en als laast de most significant byte (msb). Little-endian heet dat. De Mac gebruikt daarentegen big-endian CPU's, waar de msb als eerst wordt weggeschreven.

Daarnaast is een int tegenwoordig idd wel standaard 32 bits ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Joepie! De pack functie doet 't precies goed.

Bedankt iedereen.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
OK. Het gaat dus toch nog niet helemaal goed.

Na verbinden verwacht de server eerst een login, in de vorm van een string. Volgens de maker moet er eerst een 32-bits integer worden gestuurd met de lengte van de login-string, daarna de string, gevolgd door "\0".

Misschien begrijp ik de auteur verkeerd, dit is wat hij schrijft over integers:
Integers are sent as 4 bytes casted to an integer.
Ik heb hierover al een mail naar de maker gestuurd, of ie het misschien ietsje duidelijker kan uitleggen.

Wat ik namelijk ook stuur, de server blijft volhouden dat m'n login niet klopt. En wat de server van m'n login maakt klopt ook inderdaad niet. Als ik de server namelijk in debug-modus draai, dan krijg ik bij het uitvoeren van m'n script te zien:
Thu Mar 3 22:48:35 2005 : Server: connection established!
Thu Mar 3 22:48:35 2005 : Client authorization failed (H"–*).
Thu Mar 3 22:48:35 2005 : Server: waiting for connection on IP:port INADDR_ANY:5071
Het maakt daarbij niet uit wat ik als wachtwoord verstuur, de server schijnt altijd te denken dat ik H"–* als wachtwoord gebruikt. Dit is het script zoals ik het tot nu toe heb:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
    
    $socket = socket_create(AF_INET,SOCK_STREAM, SOL_TCP);
    $connection = socket_connect($socket, 'localhost', 5071);
    
    $pass = "whatever";
    $string_len = strlen($pass) + 1;
    
    socket_write($socket, pack("l", string_len), 4);
    socket_write($socket, $pass . "\0", $string_len);
    echo "Login send<br>";
    $data = socket_read($socket, 4);
    $unpacked = unpack("l", $data);
    echo "Response: " . $unpacked[1];
    
    socket_write($socket, pack("l", 16), 4);
    socket_close($socket);
    
?>


De response-code die ik van de server krijg klopt wel (namelijk 0: foute login), waarvan ik dus 1 moet zien te maken.

De c++ code voor het versturen van integers is (als ik tenminste het goede stukje heb gevonden, ik snap helemaal niets van c++, dus):
code:
1
2
3
4
5
6
7
void SocketCommunicator::sendInt(const int i) const {
    int wsize = sendBytes((char *) &i, sizeof(int));

    if (wsize != sizeof(int)) {
        Log::error("Big Problem when writing to Socket!");
    }
}


Misschien dat iemand met c++ kennis hier zijn licht over kan laten schijnen? Want voor mij is dat c++ allemaal abracadabra.

Acties:
  • 0 Henk 'm!

  • Shadowman
  • Registratie: Januari 2002
  • Niet online
Verwijderd schreef op donderdag 03 maart 2005 @ 23:05:

PHP:
1
2
3
    $string_len = strlen($pass) + 1;
    
    socket_write($socket, pack("l", string_len), 4);


code:
1
2
3
4
5
6
7
void SocketCommunicator::sendInt(const int i) const {
    int wsize = sendBytes((char *) &i, sizeof(int));

    if (wsize != sizeof(int)) {
        Log::error("Big Problem when writing to Socket!");
    }
}
Er mist een $ in je php-code.

De functie sendBytes geeft als ik het zo goed zie terug het aantal bytes dat is gestuurd. En dat is sizeof(int) als alles bij het versturen goed is gegaan.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
* gaat zich in een hoekje zitten schamen *

't was inderdaad die missende $
8)7 (en dat dan in het echt)

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Verwijderd schreef op donderdag 03 maart 2005 @ 23:38:
* gaat zich in een hoekje zitten schamen *

't was inderdaad die missende $
8)7 (en dat dan in het echt)
PHP:
1
error_reporting(E_ALL);

^^ Dan had je een notice gekregen. :P

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.

Pagina: 1