Sending and receiving multiple JSON literals via PHP sockets - php

I am trying send JSON data from one PHP script to another through sockets. The following is the client code
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
#socket_connect($socket, "localhost", 2429) or die("Connect could not be opened");
$arr = ["Hello", "I", "am", "a", "client"];
$count = 10;
while($count-- > 0) {
$msg = json_encode(["msg" => $arr[rand(0, 4)]]);
// tried appending \n & \0
// $msg .= "\0"; // "\n";
echo "sending $msg \n";
socket_write($socket, $msg, strlen($msg));
}
The following code is a piece of server that handles the reception:
$count = 0;
while(socket_recv($feed, $buf, 1024, 0) >= 1) {
echo "Obj ".++$count." : $buf";
// $obj = json_decode($buf); // error
}
The problem is, on the socket server side, the json_decode is unable to parse the data because of the following situation:
Expected Output:
Obj 1: {"msg":"I"}
Obj 2: {"msg":"a"}
Obj 3: {"msg":"a"}
Obj 4: {"msg":"I"}
Obj 5: {"msg":"a"}
Obj 6: {"msg":"client"}
Obj 7: {"msg":"am"}
Obj 8: {"msg":"am"}
Obj 9: {"msg":"am"}
The output I get:
Obj 1: {"msg":"I"}{"msg":"a"}{"msg":"a"}{"msg":"I"}
Obj 2: {"msg":"a"}{"msg":"client"}{"msg":"am"}{"msg":"am"}
Obj 3: {"msg":"am"}
I understand I need to tell the server end of object before sending the next one, but I do not know how. I tried to append "\n" and "\0" to tell the server end of stream, but it doesn't work. Please help me friends. Thank you in advance!

Let's try adding a length header, as that's the safest way to go when strings are involved.
Your client needs to send that information, so a slight change to your original code is in order: $msg = strlen($msg) . $msg; (right after $msg = json_encode(["msg" => $arr[rand(0, 4)]]);.
Then, assuming $socket is opened, try this as the server code (don't forget to close your sockets):
$lengthHeader = '';
$jsonLiteral = '';
while ($byte = socket_read($socket, 1)) { // reading one number at a time
echo "Read $byte\n";
if (is_numeric($byte)) { //
$lengthHeader .= $byte;
} else if ($lengthHeader) {
echo "JSON seems to start here. So...\n";
$nextMsgLength = $lengthHeader - 1; // except the current one we've just read (usually "[" or "{")
echo "Will grab the next $nextMsgLength bytes\n";
if (($partialJson = socket_read($socket, $nextMsgLength)) === false) {
die("Bad host, bad!");
}
$jsonLiteral = $byte . $partialJson;
$lengthHeader = ''; // reset the length header
echo "Grabbed JSON: $jsonLiteral\n";
} else {
echo "Nothing to grab\n";
}
}

you use socket_write function for other socket. When you add EOF char, is just for other socket recv. But you must know EOF char with that socket_write for your recv and explode it.

Related

php split data from socket_receive at carriage return and then pipe

i have somme data coming from php socket_receive function and it;s like this :
ZC* |000195000000B5D0|0000|PTv1.11|ZE20S|ProBee-ZE ZR |000195000000920A|A4C0|PTv1.11|ZE20S|ProBee-ZE OK
From this i only need the mac addresses witch are like this form:"000195000000B5D0"
i want to explode the whole message at carriage return \r\n and then for every row to split again at | and insert the address into database row.
i am trying to use this code:
<?php
$out = socket_recv($socket, $buf, 2048, MSG_WAITALL);
echo "<br>MESAJ=".$buf;
$row=preg_split('#(\r\n|[\|])#', $buf);
print_r($row);
?>
in vb.net on a previous desktop application i was using this code.
Private Sub SalveazaData()
Dim list As String() = rtbComData.Text.Split(Environment.NewLine.ToCharArray())
For Each Row As String In list
If Not (Row = "AT+DSCAN=10,2" Or Row = "OK" Or Row = "") Then
Dim s As String() = Split(Row, "|")
Dim aRow As smdDataDataSet1.smdTableRow = SmdDataDataSet1.smdTable.NewsmdTableRow()
aRow.Model = "SCL-50"
aRow.AdresaUnica = s(1)
aRow.StatusModul = "ACTIVE"
Try
SmdDataDataSet1.SearchAdrese.Rows.Add(s(1))
SmdDataDataSet1.smdTable.Rows.Add(aRow)
Catch ex As Exception
Dim u As String
u = SmdTableTableAdapter.UpdateInactivActiv()
End Try
End If
Next
End Sub
Can you please help me with this? thank you
the data is long with hundreds of addresses but using this code i mannaged to split at carriage return \n\r :
MESAJ FROM=".$buf;
$row=explode("\r\n", $buf);
echo "ROW=".$row[0];
echo "ROW=".$row[1];
?>
and i get the message like this:
ROW=ZC* |000195000000B5D0|0000|PTv1.11|ZE20S|ProBee-ZE
ROW=ZR |000195000000920A|A4C0|PTv1.11|ZE20S|ProBee-ZE
Now i only need to save the |000195000000B5D0|(address) from every row in database. how can i do that?
i used this code to answer my question
// connect to server
$result = socket_connect($socket, $host, $port) or die("Could not connect to IP\n");
//send data to connected socket
socket_write($socket, $message, strlen($message)) or die("Could not send data to server\n");
echo "<br>MESAJ TO :".$message;
// get server response
$out='';
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec"=>10, "usec"=>0));
$out = socket_recv($socket, $buf, 2048, MSG_WAITALL);
echo "<br>MESAJ FROM=".$buf;
$row=explode("\r\n", $buf);
echo "<br>ROW=".$row[0];
echo "<br>ROW=".$row[1];
foreach ($row as &$s) {
$s = explode("|",$s);
echo $s[0];
echo $s[1];
echo $s[2];
$adresaUnica=$s[1];
if(mysql_query("INSERT INTO `griddata`(`adresaUnica`, `status`, `model`) VALUES ('$adresaUnica','Activ','SCL-50')"))
{
}
}
socket_close($socket);
}
?>

How to mimic a command line run with arguements inside a PHP script?

How can you mimic a command line run of a script with arguements inside a PHP script? Or is that not possible?
In other words, let's say you have the following script:
#!/usr/bin/php
<?php
require "../src/php/whatsprot.class.php";
function fgets_u($pStdn) {
$pArr = array($pStdn);
if (false === ($num_changed_streams = stream_select($pArr, $write = NULL, $except = NULL, 0))) {
print("\$ 001 Socket Error : UNABLE TO WATCH STDIN.\n");
return FALSE;
} elseif ($num_changed_streams > 0) {
return trim(fgets($pStdn, 1024));
}
}
$nickname = "WhatsAPI Test";
$sender = ""; // Mobile number with country code (but without + or 00)
$imei = ""; // MAC Address for iOS IMEI for other platform (Android/etc)
$countrycode = substr($sender, 0, 2);
$phonenumber=substr($sender, 2);
if ($argc < 2) {
echo "USAGE: ".$_SERVER['argv'][0]." [-l] [-s <phone> <message>] [-i <phone>]\n";
echo "\tphone: full number including country code, without '+' or '00'\n";
echo "\t-s: send message\n";
echo "\t-l: listen for new messages\n";
echo "\t-i: interactive conversation with <phone>\n";
exit(1);
}
$dst=$_SERVER['argv'][2];
$msg = "";
for ($i=3; $i<$argc; $i++) {
$msg .= $_SERVER['argv'][$i]." ";
}
echo "[] Logging in as '$nickname' ($sender)\n";
$wa = new WhatsProt($sender, $imei, $nickname, true);
$url = "https://r.whatsapp.net/v1/exist.php?cc=".$countrycode."&in=".$phonenumber."&udid=".$wa->encryptPassword();
$content = file_get_contents($url);
if(stristr($content,'status="ok"') === false){
echo "Wrong Password\n";
exit(0);
}
$wa->Connect();
$wa->Login();
if ($_SERVER['argv'][1] == "-i") {
echo "\n[] Interactive conversation with $dst:\n";
stream_set_timeout(STDIN,1);
while(TRUE) {
$wa->PollMessages();
$buff = $wa->GetMessages();
if(!empty($buff)){
print_r($buff);
}
$line = fgets_u(STDIN);
if ($line != "") {
if (strrchr($line, " ")) {
// needs PHP >= 5.3.0
$command = trim(strstr($line, ' ', TRUE));
} else {
$command = $line;
}
switch ($command) {
case "/query":
$dst = trim(strstr($line, ' ', FALSE));
echo "[] Interactive conversation with $dst:\n";
break;
case "/accountinfo":
echo "[] Account Info: ";
$wa->accountInfo();
break;
case "/lastseen":
echo "[] Request last seen $dst: ";
$wa->RequestLastSeen("$dst");
break;
default:
echo "[] Send message to $dst: $line\n";
$wa->Message(time()."-1", $dst , $line);
break;
}
}
}
exit(0);
}
if ($_SERVER['argv'][1] == "-l") {
echo "\n[] Listen mode:\n";
while (TRUE) {
$wa->PollMessages();
$data = $wa->GetMessages();
if(!empty($data)) print_r($data);
sleep(1);
}
exit(0);
}
echo "\n[] Request last seen $dst: ";
$wa->RequestLastSeen($dst);
echo "\n[] Send message to $dst: $msg\n";
$wa->Message(time()."-1", $dst , $msg);
echo "\n";
?>
To run this script, you are meant to go to the Command Line, down to the directory the file is in, and then type in something like php -s "whatsapp.php" "Number" "Message".
But what if I wanted to bypass the Command Line altogether and do that directly inside the script so that I can run it at any time from my Web Server, how would I do that?
First off, you should be using getopt.
In PHP it supports both short and long formats.
Usage demos are documented at the page I've linked to. In your case, I suspect you'll have difficulty detecting whether a <message> was included as your -s tag's second parameter. It will probably be easier to make the message a parameter for its own option.
$options = getopt("ls:m:i:");
if (isset($options["s"] && !isset($options["m"])) {
die("-s needs -m");
}
As for running things from a web server ... well, you pass variables to a command line PHP script using getopt() and $argv, but you pass variables from a web server using $_GET and $_POST. If you can figure out a sensible way to map $_GET variables your command line options, you should be good to go.
Note that a variety of other considerations exist when taking a command line script and running it through a web server. Permission and security go hand in hand, usually as inverse functions of each other. That is, if you open up permissions so that it's allowed to do what it needs, you may expose or even create vulnerabilities on your server. I don't recommend you do this unless you'll more experienced, or you don't mind if things break or get attacked by script kiddies out to 0wn your server.
You're looking for backticks, see
http://php.net/manual/en/language.operators.execution.php
Or you can use shell_exec()
http://www.php.net/manual/en/function.shell-exec.php

PHP and Python unpack return different results from same source

I cannot seem to get even vaguely the same data from the Python (Which I would prefer to use) and PHP (Which works fine, coded by the host of the website) scripts.
PHP connects to the same location as the Python script.
And before anyone jumps the gun, I know the python script only retrieves a part of the data. But I can't get even vaguely the same data from the server.
Python:
import socket, struct
host,port = 'baystation12.net', 8000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.send('status\r\n')
data = s.recv(1024)
s.close()
print 'Received:', repr(data) # >>> Received: '\x00\xc7\x00\x07\x02\xadj\x00\x00\x1c\xf6'
cache,form,listy = "",">H",[]
for i in data:
if cache != "":
listy.append(struct.unpack(form,cache+i))
else:
cache = i
print "Unpacked:",listy # >>> Unpacked: [(199,), (0,), (7,), (2,), (173,), (106,), (0,), (0,), (28,), (246,)]
text = ""
for i in listy:
text += chr(i[0])
print "Text:",text # >>> Text: Ç
#Shows up incorrectly when I try to copy it.
PHP:
#!/usr/bin/php
<?php
function export($addr,$port,$str)
{
if($str{0} != "?") $str = ("?" . $str);
$query = "\x00\x83" . pack("n",strlen($str)+6) . "\x00\x00\x00\x00\x00" . $str . "\x00";
$server = socket_create(AF_INET,SOCK_STREAM,SOL_TCP) or exit('Unable to create export socket; ' . socket_strerror(socket_last_error()));
socket_connect($server,$addr,$port) or exit('Unable to establish socket connection; ' . socket_strerror(socket_last_error()));
$bytessent = 0;
while($bytessent < strlen($query))
{
$result = socket_write($server,substr($query,$bytessent),strlen($query)-$bytessent);
if($result === FALSE) return('Unable to transfer requested data; ' . socket_strerror(socket_last_error()));
$bytessent += $result;
}
$resbuf = '';
while( socket_recv($server, $message,1,0 )){
$resbuf .= $message;
if(strpos($resbuf,"&end")!=FALSE)
{
echo $resbuf;
socket_close($server);
return($resbuf);
}
echo $message;
};
echo $resbuf."\n";
socket_close($server);
}
export("localhost","8000","status");
?>
PHP's output:
version=Baystation+12&mode=extended&respawn=0&enter=1&vote=1&ai=1&host&players=5&player0=CompactNinja&player1=Sick+trigger&player2=SweetJealousy&player3=Cacophony&player4=Anchorshag&end
Any idea why Python gives out nonsensical characters when unpacking the data, while PHP gives out the above.
You're not sending the same query to your server in python.
In python you're sending status
In PHP you're sending something like \x00\x83\x00\x0d\x00\x00\x00\x00\x00\x00?status\x00
If you change your python to more closely imitate the PHP then it works a lot better:
import socket, struct
host,port = 'baystation12.net', 8000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
senddata = "?status"
query = '\x00\x83' + struct.pack(">H", len(senddata)+6) + '\x00'*5 + senddata + '\x00'
s.send(query)
data = s.recv(1024)
print `data`
When I tried that, it printed
'\x00\x83\x00\xe9\x06version=Baystation+12&mode=traitor&respawn=0&enter=1&vote=1&ai=1&host&players=7&player0=Kosherman&player1=Ghazkull&player2=Doug+H.+Nuts&player3=Lord+Braindead&player4=KirbyElder&player5=Master+of+Apples&player6=Cacophony&end=%23end\x00'
Which looks pretty similar to what the PHP was getting.
Try listy.append(struct.unpack(form,cache+i)[0])
You're ending up with a list of 1-element tuples rather than the a list of numbers.
From the docs: http://docs.python.org/library/struct.html#struct.unpack
struct.unpack(fmt, string)
Unpack the string (presumably packed by
pack(fmt, ...)) according to the given format. The result is a tuple
even if it contains exactly one item. The string must contain exactly
the amount of data required by the format (len(string) must equal
calcsize(fmt)).

IRC related help

Now I have my bot to send message when the bot joins. However how do I make a form that would post data so that the bot will say the message to the channel?
Here is my script (Rewamped):
<?php
set_time_limit(0);
$socket = fsockopen("//", 6667) or die();
$msg = $_POST['message'];
$pr = $_POST['percentage'];
$pr /= 100;
fputs($socket,"USER BOT 0 zo :ZH bot\n");
// Set the bots nickname
fputs($socket,"NICK BOT1\n");
fputs($socket,"JOIN #bots\n");
while(1) {
while($data = fgets($socket, 128)) {
// echo the data received to page
echo nl2br($data);
// flush old data, it isn't needed any longer.
flush();
$ex = explode(' ', $data);
if($ex[0] == "PING") fputs($socket, "PONG ".$ex[1]."\n");
$search_string = "/^:([A-Za-z0-9_\-]+)[#!~a-zA-Z0-9#\.\-]+\s*([A-Z]+)\s*[:]*([\#a-zA-Z0-9\-]+)*\s*[:]*([!\#\-\.A-Za-z0-9 ]+)*/";
$do = preg_match($search_string, $data, $matches);
// check that there is a command received
if(isset($matches['2'])) {
switch($matches['2']) {
case "PRIVMSG":
$user = $matches['1'];
$channel = $matches['3'];
$chat_text = isset($matches['4']) ? $matches['4'] : "";
// check chat for !time
if(strtolower($chat_text) == "!time") {
$output = "::::: " . date('l jS \of F Y h:i:s A') . " :::::";
fputs($socket, "PRIVMSG " . $channel . " :" . $output . "\n");
} elseif(strtolower($chat_text) == "!hello") {
fputs($socket, "PRIVMSG " . $channel . " :Hello!\n");
}
break;
case "JOIN":
$user = $matches['1'];
$channel = $matches['3'];
fputs($socket, "PRIVMSG " . $channel . " :Welcome " . $user . " to " . $channel . "\n");
break;
}
}
}
}
?>
E.g. Making a form that would send the data to the IRC channel. The output would be "wget file info port" <-- That would be the text sent to the IRC channel.
Here are parts related:
fputs($socket, "PRIVMSG " . $channel . " :Welcome " . $user . " to " . $channel ."\n");
Hope someone can help out.
Okay here's a better answer. The first section still stands. A new PHP process is called every time you want to initiate a new script. Thus, you need some way to do IPC.
Here's how it's done on *nix (but not windows) in PHP:
Receiver:
<?php
$queueKey = 123321;
$queue = false;
if(msg_queue_exists($queueKey)) {
echo "Queue Exists.\n";
}
// Join the queue
$queue = msg_get_queue($queueKey);
while(!($queue == false)) {
// Note: This function could block if you feel like threading
$msgRec = msg_receive(
$queue, // I: Queue to get messages from
0, // I: Message type (0 = first on queue)
$msgType, // O: Type of message received
1024, // I: Max message size
$msgData, // O: Data in the message
true, // I: Unserialize data
MSG_IPC_NOWAIT // I: Don't block
);
if($msgRec) {
echo "Message received:\n";
echo "Type = $msgType\n";
echo "Data = \n";
print_r($msgData);
}
}
?>
Sender:
<?php
$queueKey = 123321;
$queue = false;
if(msg_queue_exists($queueKey)) {
echo "Queue Exists.\n";
} else {
echo "WARNING: Queue does not exist. Maybe no listeners?\n";
}
$queue = msg_get_queue($queueKey);
$abc["something"] = "something value";
$abc["hello"] = "world";
$abc["fu"] = "bar";
msg_send(
$queue, // Queue to send on
1, // Message type
$abc, // Data to send
true, // Serialize data?
true // Block
);
?>
This should produce (in the receiver loop) something similar to this:
Message received:
Type = 1
Data =
Array
(
[something] => something value
[hello] => world
[fu] => bar
)
Your script might look something like this
postToMe.php:
<?php
$queueKey = 123321;
$queue = false;
if(msg_queue_exists($queueKey)) {
echo "Queue Exists.\n";
} else {
echo "WARNING: Queue does not exist. Maybe no listeners?\n";
}
$queue = msg_get_queue($queueKey);
msg_send(
$queue, // Queue to send on
1, // Message type
$_POST, // Data to send
true, // Serialize data?
true // Block
);
?>
bot.php:
<?php
set_time_limit(0);
$socket = fsockopen("//", 6667) or die();
$msg = $_POST['message'];
$pr = $_POST['percentage'];
$pr /= 100;
fputs($socket,"USER BOT 0 zo :ZH bot\n");
// Set the bots nickname
fputs($socket,"NICK BOT1\n");
fputs($socket,"JOIN #bots\n");
$queueKey = 123321;
$queue = false;
// Join the IPC queue
$queue = msg_get_queue($queueKey);
if(!$queue) echo "ERROR: Could not join IPC queue. Form data will not be received";
while(1) {
// Handle new post info
// You may want to increase the message size from 1024 if post data is large
if(msg_receive($queue, 0, $msgType, 1024, $msgData, true, MSG_IPC_NOWAIT)) {
// Handle data here. Post data is stored in $msgData
}
while($data = fgets($socket, 128)) {
// echo the data received to page
echo nl2br($data);
// flush old data, it isn't needed any longer.
flush();
$ex = explode(' ', $data);
if($ex[0] == "PING") fputs($socket, "PONG ".$ex[1]."\n");
$search_string = "/^:([A-Za-z0-9_\-]+)[#!~a-zA-Z0-9#\.\-]+\s*([A-Z]+)\s*[:]*([\#a-zA-Z0-9\-]+)*\s*[:]*([!\#\-\.A-Za-z0-9 ]+)*/";
$do = preg_match($search_string, $data, $matches);
// check that there is a command received
if(isset($matches['2'])) {
switch($matches['2']) {
case "PRIVMSG":
$user = $matches['1'];
$channel = $matches['3'];
$chat_text = isset($matches['4']) ? $matches['4'] : "";
// check chat for !time
if(strtolower($chat_text) == "!time") {
$output = "::::: " . date('l jS \of F Y h:i:s A') . " :::::";
fputs($socket, "PRIVMSG " . $channel . " :" . $output . "\n");
} elseif(strtolower($chat_text) == "!hello") {
fputs($socket, "PRIVMSG " . $channel . " :Hello!\n");
}
break;
case "JOIN":
$user = $matches['1'];
$channel = $matches['3'];
fputs($socket, "PRIVMSG " . $channel . " :Welcome " . $user . " to " . $channel . "\n");
break;
}
}
}
}
?>
Basically, this script will be running all the time. The way PHP works is that for each script that is being run, a new PHP process is created. Scripts can be run multiple times simultaneously, however they will not be able to directly communicate.
You will need to create enother script (or at least a whole new function of this one) to accept the post variables, and then send them to the running version of this script.
(Note: I will provide 2 solutions, since 1 is significantly more difficult. Also, there's Semaphore that I've just found, however I am unsure exactly if this suits our needs because I know next to nothing about it http://php.net/manual/en/book.sem.php)
Best (But Advanced)
The best way I can think of doing this would be to use sockets (particularly on *nix, since sockets are fantastic for IPC [inter process communication]). It's a little difficult, since you're basically create a client/server just to communicate details, then you need to come up with some sort of a protocol for your IPC.
I won't code anything up here, but the links that are relevant to this are
http://www.php.net/manual/en/function.socket-create.php
http://www.php.net/manual/en/function.socket-bind.php
http://www.php.net/manual/en/function.socket-listen.php
http://www.php.net/manual/en/function.socket-accept.php
http://www.php.net/manual/en/function.socket-connect.php
If using this on *nix, I would highly recommend using AF_UNIX as the domain. It's very efficient, and quite a number of applications use it for IPC.
Pros:
Very robust solution
- Highly efficient
- Instant (or as close as we can get) communication
Cons:
- Quite difficult to implement
Not As Great (But Still Good)
Just use files to communicate the information. Have your bot script check the file every 15 seconds for changes. I would suggest using XML for the data (since simple xml makes xml processing in php well... simple)
Things you need to consider would be:
How would it react when receiving 2 posts at the same time? (If you just use a flat file or don't account for having multiple entries, this will become a problem).
How you find out if a message is new (I'd delete/blank the file right after reading. Note: Not after processing, as someone could post to the form script while you are processing/sending the message)
Links:
How to use simple xml
http://php.net/manual/en/simplexml.examples-basic.php
http://au2.php.net/manual/en/book.simplexml.php
File related
http://au2.php.net/manual/en/function.file-put-contents.php
http://au2.php.net/manual/en/function.file-get-contents.php
With that being said, you could also use MySQL/Postgres or some other database back end to deal with the flow of data between scripts.
Pros:
- Easy to implement
Cons:
- Slow to transfer data (checks files at given intervals)
- Uses external files, which can be deleted/modified my external applications/users

php telnet no response from script

I'm running PHP5 on Windows XP Professional. I'm trying to write a telnet php script which simply connects, sends a text string and grabs the response buffer and outputs it. I'm using the telnet class file from here:
http://cvs.adfinis.ch/cvs.php/phpStreamcast/telnet.class.php
which i found in another thread.
<?php
error_reporting(255);
ini_set('display_errors', true);
echo "1<br>";
require_once("telnet_class.php");
$telnet = new Telnet();
$telnet->set_host("10.10.5.7");
$telnet->set_port("2002");
$telnet->connect();
//$telnet->wait_prompt();
$telnet->write('SNRD 1%0d');
echo "3<br>";
$result = $telnet->get_buffer();
echo $result;
print_r($result);
// flush_now();
echo "4<br>";
$telnet->disconnect();
?>
I'm not receiving any kind of errors or response. If I send an invalid string, I should get an 'ERR' response in the least however I don't even get that. Any ideas what i could be doing wrong? If I do the same thing from the command prompt, I receive the string output I need. Could this is because the write function is sending
After some reading in the source code and on the original (french) site referred to in the header....
<?php
error_reporting(255);
ini_set('display_errors', true);
echo "1<br>";
require_once("telnet_class.php");
$telnet = new Telnet();
$telnet->set_host("10.10.5.7");
$telnet->set_port("2002");
if ($telnet->connect() != TELNET_OK) {
printf("Telnet error on connect, %s\n",$telnet->get_last_error());
}
//$telnet->wait_prompt();
if ($telnet->write('SNRD 1' . "\xd") != TELNET_OK) {
printf("Telnet error on write, %s\n",$telnet->get_last_error());
}
// read to \n or whatever terminates the string you need to read
if ($telnet->read_to("\n") != TELNET_OK) {
printf("Telnet error on read_to, %s\n",$telnet->get_last_error());
}
echo "3<br>";
$result = $telnet->get_buffer();
echo $result;
print_r($result);
// flush_now();
echo "4<br>";
$telnet->disconnect();
?>
Okay, explanation: get_buffer() does just that, read what's in the buffer. To get something in the buffer you have to execute read_to($match) who will read into buffer up to $match. After that, get_buffer should give you the desired string.
EDIT:
if you cannot find some string that follows the string you are interested in read_to will end in an error due to this part of the read_to method (translation of original french comment is mine):
if ($c === false){
// plus de caracteres a lire sur la socket
// --> no more characters to read on the socket
if ($this->contientErreur($buf)){
return TELNET_ERROR;
}
$this->error = " Couldn't find the requested : '" . $chaine . "', it was not in the data returned from server : '" . $buf . "'" ;
$this->logger($this->error);
return TELNET_ERROR;
}
Meaning that when the socket is closed without a match of the requested string, TELNET_ERROR will be returned. However, the string you're looking for should at that point be in the buffer.... What did you put in read_to's argument? "\n" like what I did or just "" ?
EDIT2 :
there's also a problem with get_buffer. IMO this class is not really a timesaver ;-)
//------------------------------------------------------------------------
function get_buffer(){
$buf = $this->buffer;
// cut last line (is always prompt)
$buf = explode("\n", $buf);
unset($buf[count($buf)-1]);
$buf = join("\n",$buf);
return trim($buf);
}
It will throw away the last line of the response, in your case the one that contains the
answer.
I suggest to add a "light" version of get_buffer to the class, like this
//------------------------------------------------------------------------
function get_raw_buffer(){
return $this->buffer;
}
and do the necessary trimming/searching in the result yourself.
You might also want to add the following constant
define ("TELNET_EOF", 3);
and change read_to like this
...
if ($c === false){
// plus de caracteres a lire sur la socket
if ($this->contientErreur($buf)){
return TELNET_EOF;
}
$this->error = " Couldn't find the requested : '" . $chaine . "', it was not in the data returned from server : '" . $buf . "'" ;
$this->logger($this->error);
return TELNET_EOF;
}
...
in order to treat that special case yourself (a result code TELNET_EOF doesn't have to be treated as an error in your case). So finally your code should look more or less like this:
// read to \n or whatever terminates the string you need to read
if ($telnet->read_to("\n") == TELNET_ERROR) {
printf("Telnet error on read_to, %s\n",$telnet->get_last_error()); } echo "3<br>";
} else {
$result = $telnet->get_raw_buffer();
echo $result;
print_r($result);
}
Have you checked how the telnet class works? Maybe it wasn't designed to run under windows. If it's a simple socket that you're speaking to, maybe consider using a regular socket-connection instead.
http://se2.php.net/sockets
If you open up a socket which you don't close, you should se an entry in netstat as long as your script is running.
netstat -na|find ":2002"
You can't insert hex values like that. The remote process just sees
SRND 1%0d
and now it's waiting for the line to be terminated. Try this
$telnet->write('SNRD 1' . "\r");
or
$telnet->write("SNRD 1\xd");
The double quotes are quite critical, see here
EDIT:
you might try adding some error reporting as right now you don't really check much (error_reporting won't show anything on the errors in the telnet class).... For example:
<?php
error_reporting(255);
ini_set('display_errors', true);
echo "1<br>";
require_once("telnet_class.php");
$telnet = new Telnet();
$telnet->set_host("10.10.5.7");
$telnet->set_port("2002");
if ($telnet->connect() != TELNET_OK) {
printf("Telnet error on connect, %s\n",$telnet->get_last_error());
}
//$telnet->wait_prompt();
if ($telnet->write('SNRD 1' . "\xd") != TELNET_OK) {
printf("Telnet error on write, %s\n",$telnet->get_last_error());
}
echo "3<br>";
$result = $telnet->get_buffer();
echo $result;
print_r($result);
// flush_now();
echo "4<br>";
$telnet->disconnect();
?>
also, are you sure you need \r\n line termination? write is defined as
function write($buffer, $valeurLoggee = "", $ajouterfinLigne = true){
and does
if ($ajouterfinLigne){
$buffer .= "\n";
}
?
Also, did you test the host and port with the command line telnet client? Like
telnet 10.10.5.7 2002
?

Categories