I'm looking for a guide on how to use fsockopen() to communicate with a telnet system.... I'm connected just fine, but the command is failing to send. I've seen some documentation fwrite() that shows people sending some headers.
Currently the command I'm running against the telnet server is version via $class->send("version");. Do I need to send headers or anything along with this for the telnet server to pick up the command, or can I just send that?
/**
* Connect to the GMC telnet system
*/
public function connect () {
$this->connection = fsockopen($this->socket['host'], $this->socket['port'], $errorNumber, $errorMessage, 30);
if (!$this->connection) {
$this->error = 'Unable to connect to GMC: '.$errorMessage.' ('.$errorNumber.')';
return false;
}
stream_set_timeout($this->connection, $this->commandTimeout);
return true;
}
/**
* Send a command to GMC
*/
public function send ($command) {
//write to socket
if (fwrite($this->connection, $command) === false) {
$this->error = 'Unable to write to socket';
return false;
}
sleep(1);
//read socket
if (($response = fgets($this->connection)) === false) {
$this->error = 'Unable to write to socket';
return false;
}
return $response;
}
/**
* Disconnects from the GMC telnet system
*/
public function disconnect () {
return fclose($this->connection);
}
Apparently all I needed to do was be sure I included a \n at the end of my command!!
Related
I use workerman/workerman for websockets.
The main question – how to send messages on websocket closing?
Also I tried to send messages to other connections. No result too.
public function run()
{
$this->ws = new Worker(
'websocket://0.0.0.0:' . $_ENV['WS_PORT'],
['ssl' => [
'local_cert' => $_ENV['WS_CERTIFICATE_CRT'],
'local_pk' => $_ENV['WS_CERTIFICATE_KEY'],
'verify_peer' => false,
]]
);
$this->ws->count = 1;
$this->ws->transport = 'ssl';
$this->ws->onConnect = function ($connection) {
$this->onConnect($connection);
};
$this->ws->onMessage = function ($connection, $data) {
$this->onMessage($connection, $data);
};
$this->ws->onClose = function ($connection) {
$this->onClose($connection);
};
Worker::runAll();
}
This doesn't work
private function onClose($connection)
{
$connection->send("Hello");
}
Looking at the source code of workerman/workerman we can see that the onClose event is implemented as follows:
// Close socket.
try {
#fclose($this->socket);
} catch (Throwable) {
}
$this->status = self::STATUS_CLOSED;
// Try to emit onClose callback.
if ($this->onClose) {
try {
($this->onClose)($this);
} catch (Throwable $e) {
$this->error($e);
}
}
As you can see, onClose is emitted AFTER the socket has been closed.
So you will not be able to use that socket in your onClose handler anymore.
A better solution would be that the client sends some sort of "close" packet to the server.
The server can then run some logic and close the connection after it is done.
I successfully insttalled PAMI in my server where asterisk is setup. And i wrote a new php file which
class A implements IEventListener
{
public function handle(EventMessage $event)
{
print_r("Inside");
}
}
$pamiClient = new PamiClient($pamiClientOptions);
$pamiClient->registerEventListener(new A());
$pamiClient->open();
$running = true;
while($running) {
$pamiClient->process();
usleep(1000);
}
$pamiClient->close();
But when i generate a call it doesnot catch the event. How can i know it is connected with asterisk, and how can i test this? Iam justng running this php file .
How i can know it connected to asterisk:
tcpdump -vv dst port 5038
how can i test this
Use debugger.
I know socket and thread is horrible in php... I'm just trying to connect my php file with socket to my server.
The problem is I got nothing from socket_read (no datas no error just returning an empty string) and I think pthread kill automatically the socket.
For now I don't need thread but I need to keep it to use it later.
My code:
<?php
class test extends Threaded
{
/*
*/
public function __construct($ip, $port, $debug = false)
{
$this->debug = $debug;
$this->ip = $ip;
$this->port = $port;
}
/*
*/
public function __destruct()
{
socket_close($this->connect);
}
/*
*/
public function start()
{
if (!($this->connect = socket_create(AF_INET, SOCK_STREAM, SOL_TCP))) {
throw new Exception('SOCKET_CREATE');
}
if (!socket_set_option($this->connect, SOL_SOCKET, SO_RCVTIMEO, array('sec' => 5, 'usec' => 0))) {
throw new Exception('SOCKET_SET_OPTION');
}
if (!socket_connect($this->connect, $this->ip, $this->port)) {
throw new Exception('SOCKET_CONNECT');
}
$getMsg = socket_read($this->connect, 255);
echo $getMsg;
}
}
Do you know how it can works?
EDIT: I tried again today and my script works, I don't understand sometime it works sometime not ....
EDIT2: I copied my server file script to an other server with much much more traffic and it works ! So why it works on the server 2 and not on server 1 ?
I've been having issues with reading data from a Python socket server. I've tried several methods and have been searching for a solution for months.
The response I am trying to get from the Python socket server is different every time. It can be 40 characters the first time and over 10k characters the next.
I've tried to use socket_recv() and fgets() and so far fgets works the best for what I need, as socket_recv doesn't get the whole response when fgets does. There's just one problem. It's so much slower compared to socket_recv, and doesn't always get the response.
The problem I am having with fgets is that it takes 2.02 seconds to get the response on a local connection, no matter how big or small it is.
I need it to go down, but I can't for the life of me figure out how to fix it..
Connecting to the Python socket server only takes 22ms, so I don't get why it'd take long at all to get the whole reponse.
Oh and if it helps, the response is a JSON string.
Here's the code I use:
/*
* Recieve
*/
public function recv() {
if (!$this->connected()) {
$this->_errorStr = 'Recieve timeout';
$this->_error = true;
return false;
}
$buf = '';
while ($line = fgets($this->_socket)) {
$buf .= $line;
}
return json_decode($buf);
}
And if you need the whole class:
class Sockets {
/*
* Variables
*/
private $_id,
$_name,
$_ip,
$_port,
$_socket,
$_socketTimeout = 1,
$_triedConnect = false,
$_errorStr = '',
$_error = false;
/*
* Construct class
*/
public function __construct($ip, $port) {
$this->_ip = $ip;
$this->_port = $port;
$this->_socket = false;
}
/*
* Send command
*/
public function command($cmd, $json = true) {
if ($json) {
$cmd = json_encode($cmd);
}
if (!$this->send($cmd)) {
return $this->_errorStr;
}
$r = $this->recv();
if (!$r) {
return $this->_errorStr;
}
return $r;
}
/*
* Connect to server
*/
public function connect() {
$this->_error = false;
if ($this->_triedConnect) {
$this->_errorStr = 'Failed to connect.';
$this->_error = true;
return false;
}
$this->_triedConnect = true;
$this->_errorStr = '';
$errno = 0;
$errstr = '';
$this->_socket = #pfsockopen($this->_ip, $this->_port, $errno, $errstr, $this->_socketTimeout);
if (!$this->_socket) {
$this->_errorStr = sprintf('Can\'t connect to server.. (%errno: %errstr)', $errno, $errstr);
$this->_error = true;
$this->_socket = false;
return false;
}
stream_set_timeout($this->_socket, $this->_socketTimeout);
// Clear stream
while ($this->dataReady()) {
if (!fgets($this->_socket)) {
break;
}
}
if (!$this->connected()) {
$this->_errorStr = 'Lost connection to server!';
$this->_error = true;
$this->_socket = false;
return $this->_errorStr;
}
return true;
}
/*
* Authentication
*/
public function auth() {
}
/*
* Connected
*/
public function connected() {
return $this->_socket !== false;
}
/*
* Data ready
*/
public function dataReady() {
if (!$this->connected()) {
return false;
}
return #stream_select($r = array($this->_socket), $w = null, $x = null, 0) > 0;
}
/*
* Send data
*/
public function send($data) {
if (!$this->connected()) {
$this->_errorStr = 'Not connected!';
$this->_error = true;
return false;
}
if (#fwrite($this->_socket, $data) === false) {
$this->_errorStr = 'Failed to send command!';
$this->_error = true;
return false;
}
return true;
}
/*
* Recieve
*/
public function recv() {
if (!$this->connected()) {
$this->_errorStr = 'Recieve timeout';
$this->_error = true;
return false;
}
$buf = '';
while ($line = fgets($this->_socket)) {
$buf .= $line;
}
return json_decode($buf);
}
/*
* Disconnect
*/
public function disconnect() {
if (!$this->connected()) {
return;
}
fclose($this->_socket);
$this->_socket = false;
$this->_triedConnect = false;
}
}
Any help is really appreciated!
EDIT
The machine I am using is running Windows 8.1 Pro, with Media Center.
I am using Python 2.7.9 for the server with the following dependencies installed:
psutil <- https://pypi.python.org/pypi/psutil
colorama <- https://pypi.python.org/pypi/colorama
pycrypto <- http://www.voidspace.org.uk/python/modules.shtml#pycrypto
It shouldn't matter what type of TCP socket server at all. Just a basic one should work just to test this. Even without the dependencies. Something like this works.
For PHP I am using Wamp and PHP 5.5.12 with the following modules enabled:
php_bz2
php_com_dotnet
php_curl
php_exif
php_fileinfo
php_gd2
php_gettext
php_gmp
php_imap
php_intl
php_ldap
php_mbstring
php_mysql
php_mysqli
php_openssl
php_pdo_mysql
php_pdo_sqlite
php_shmop
php_soap
php_sockets
php_sqlite3
php_xmlrpc
php_xsl
Some, if not all of those, are enabled on default.
To test the Sockets class, all you need is to is something like this:
// Import class file
require_once 'Sockets.php';
$socket = new Sockets('127.0.0.1', 21); // Change the port accordingly
// Connect to socket server
$socket->connect();
// Now in my case, the socket server responds to JSON strings, and nothing else.
// So I am going to show you show I send a command.
$command = array(
'key' => 'encrypted key', // This key is to do some validation on the server-side
'command' => 'command' // This is the command to be issued.
);
// Send command to socket server and dump the response
var_dump($socket->command($command));
// To send a plainstring command use this instead
var_dump($socket->command('command here', false));
After quite a lot of debugging and further searching the interwebs and not finding anything, I finally found an answer to my issue.
The issue was with the Python socket server. After sending a command to the socket server, it sends a response back with the requested data. The socket server should then close the connection. And this is where the issue was. It was sending the response, but not closing the connection, so all I had to do was close the connection after every command. The response time went from 2.02 seconds down to 20ms, which is what I wanted.
I recently found out that PHP not only has the fsock* functions, but also functions to create a server itself. I decided to experiment a little bit, and came up with this. Now, the problem is that it hangs on accept_connection() (due to the fact that it's waiting for a connection.) I found out that the solution is to use stream_set_blocking(), which as you can see, I attempted, but to no avail.
I am getting an error message, which reads:
Warning: socket_set_blocking(): supplied resource is not a valid stream resource in /home/insomniaque/workspace/PHP Socket RAT/rat.class.php on line 68
I know that accept_connection() was the problem earlier because when I would connect with a second connection, it would output the data.
<?php
/*
* Project: iRAT
*
* Created on Jan 11, 2010
* Written by Insomniaque
*
*/
class rat
{
/**
* Holds the PHP socket handle for use within the class.
*/
private $socket;
/**
* Holds an array of all the spawned sockets (child sockets) that were
* created when a user connected to the server.
*/
private $spawns = array ();
/**
* Holds the maximum number of connections.
*/
private $maxconn;
/**
* Sets all of the variables required for the class and starts the socket.
* Then it'll start looping, connecting clients and running commands.
*
* #access public
* #param $port The port to bind.
* #param $maxconn The maximum number of client connections.
*/
public function __construct($port = 0, $maxconn = 1)
{
/**
* Check to see if the user has entered 0 as the port, and create a
* random port, if so.
*/
if($port == 0)
$this->port = rand(81, 8079);
else
$this->port = $port;
/**
* Save the maximum connection number.
*/
$this->maxconn = $maxconn;
/**
* Run our function to create the socket now.
*/
if(!$this->createSocket())
{
echo "Failed creating or binding socket.\n";
return false;
}
else
{
echo "Socket has been created and binded.\n";
}
/**
* Turn non-blocking on so we can run multiple clients.
*/
socket_set_blocking($this->socket, 0);
echo "Starting the data receiving loop.\n";
$this->startLoop();
return true;
}
/**
* This function will create the socket for later use.
*
* #access private
* #return bool Returns true if the socket was created successfully,
* returns false if there was an error.
*/
private function createSocket()
{
/**
* Create a socket of IPv4 type using the TCP gateway.
*/
$this->socket = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp'));
if(!$this->socket)
return false;
echo "Socket has been created.\n";
/**
* Attempt to bind the socket to localhost:[port]
*/
do
{
if(!isset($i))
$i++;
$port = $this->port;
$bind = socket_bind($this->socket, 0, $port);
if(!$bind)
{
$i++;
$this->port = rand(79, 8079);
}
} while(!$bind && $i <= 5);
if($i == 5)
return false;
echo "Port ".$this->port." has been binded to the RAT.\n";
return true;
}
/**
* Start a loop running on our socket. We will check if we are getting
* data, accept connections and run any commands. When the connection
* is closed, we will return true.
*
* #access private
* #return bool Returns false if the socket can't be listened to. Otherwise
* returns true when the socket is closed.
*/
private function startLoop()
{
if(socket_listen($this->socket, 3))
{
while(true)
{
if(($newspawn = socket_accept($this->socket)) !== false)
{
$this->spawns[] = $newspawn;
echo "A new spawn has connected.";
} else
echo "No new socket";
sleep(1000);
foreach($this->spawns as $key => $spawn)
{
$data = trim(socket_read($spawn, 1024));
if(strlen($data) > 0)
{
if($data == "exit")
{
socket_close($spawn);
unset($this->spawns[$key]);
echo "Spawn killed.\n";
}
if($data == "kill")
{
foreach($this->spawns as $key => $spawn)
{
socket_close($spawn);
unset($this->spawns[$key]);
}
socket_close($this->socket);
echo "Socket closed.\n";
return true;
}
else
{
echo "Data: " . $data . "\n";
}
}
}
}
}
else
{
echo "Failure receiving data.\n";
return false;
}
}
}
?>
Thanks in advance,
John
Use socket_set_nonblock() instead of socket_set_blocking() for a socket resource create by socket_create().
socket_set_blocking() is an alias for
stream_set_blocking() which only works for (php-)streams, like the result of fopen() or stream_socket_create()
edit: You can also use socket_select() or stream_select() to handle both new connections and client data packet, e.g.
private function createSocket()
{
$this->socket = stream_socket_server('tcp://0.0.0.0:'.(int)$this->port, $errno, $errstr);
if(!$this->socket) {
$this->socket = null;
echo "stream_socket_server failed : $errstr ($errno)\n";
return false;
}
echo "Port ".$this->port." has been bound to the RAT.\n";
return true;
}
public function startLoop() {
if ( is_null($this->socket) ) {
return false;
}
$write = array(); $exception=array();
while( !$this->shutdown ) {
// stream_select() alters the array, so $read has to be re-constructed in each iteration somehow
$read = array_merge(array($this->socket), $this->spawns);
// you might want to check $exception as well
if ( 0!==stream_select($read, $write, $exception, 4) ) {
// $now $read only contains those sockets, that will not block
// for fread/accept operations
foreach($read as $s) {
if ( $s===$this->socket ) {
$this->onAccept();
}
else {
$this->onClientPacket($s);
}
}
}
}
$this->shutdown();
}
Keep in mind that if a client sends two commands like e.g.
$fp1 = stream_socket_client("tcp://localhost:81", $errno, $errstr, 30);
fwrite($fp1, "1 blabla");
fwrite($fp1, "exit");
it doesn't necessarily mean your server will get two separate messages.
I believe you would be interested in using stream_socket_create() as opposed to socket_create(), which should return a valid resource to be used with socket_set_blocking().
Note that you will also need to utilize stream_socket_accept() to begin accepting connections on your newly created socket.