I am new to socket programming. I have a GPS Tracker that connects and send data to a defined public server:port through GPRS connection.
I am getting the result on the terminal.
I want to know how can I get that response in some variable so I can save those entries in database real-time.
Here is the code.
require_once("SocketServer.class.php"); // Include the File
$server = new SocketServer("xxx.xx.x.xxx",8153); // Create a Server binding to the given ip address and listen to port 31337 for connections
$server->max_clients = 10; // Allow no more than 10 people to connect at a time
$server->hook("CONNECT","handle_connect"); // Run handle_connect every time someone connects
$server->hook("INPUT","handle_input"); // Run handle_input whenever text is sent to the server
$server->infinite_loop(); // Run Server Code Until Process is terminated.
function handle_connect(&$server,&$client,$input)
{
SocketServer::socket_write_smart($client->socket,"String? ","");
}
function handle_input(&$server,&$client,$input)
{
// You probably want to sanitize your inputs here
$trim = trim($input); // Trim the input, Remove Line Endings and Extra Whitespace.
if(strtolower($trim) == "quit") // User Wants to quit the server
{
SocketServer::socket_write_smart($client->socket,"Oh... Goodbye..."); // Give the user a sad goodbye message, meany!
$server->disconnect($client->server_clients_index); // Disconnect this client.
return; // Ends the function
}
$output = strrev($trim); // Reverse the String
echo "output is".$trim;
SocketServer::socket_write_smart($client->socket,$output); // Send the Client back the String
SocketServer::socket_write_smart($client->socket,"String? ",""); // Request Another String
}
SocketServer.class.php
http://www.phpclasses.org/browse/file/31975.html
This line doesn't print the result on terminal
echo "output is".$trim;
I have tried this as well
$myfile = fopen("file.txt", "w") or die("Unable to open file!");
fwrite($myfile, $trim);
fclose($myfile);
and the file remain empty
Go to SocketServer.class.php and look for this code
the result is in this variable $input. So if you want to save data into database then add your code in else part.
if($input == null){
$this->disconnect($i);
}else{
SocketServer::debug("{$i}#{$this->clients[$i]->ip} --> {$input}");
$data= $input;
//add your code here
Note: The author has updated the code of its library. Here is the new code
https://github.com/navarr/Sockets
Related
Alright, so first of all, i'm still kind of a newbie in PHP.
I'm trying to make a chatbot that responds to the keyword "shut up" from people that tell that to the bot in my game server, but I can't seem to find a way how...
Here's the bot's original code...
<?php
$choosechar = "#43CC#1#35#ItsJustABot#%";
$fh = fopen('badtimetim.txt','r');
$word_array = array(fgets($fh));
$word = rand(0,58);
$lines = file("badtimetim.txt");
while ($line = fgets($fh)) {
// <... Do your work with the line ...>
// echo($line);
// Connect to the AO Server
if (!($fp = fsockopen("127.0.0.1", "27017", $errno, $errstr, 15))) {
die("Failed to connect. Doesn't seem like the server is up anyway?");
}
// Set timeout to 1 second
if (!stream_set_timeout($fp, 1)) die("Could not set timeout.");
// Fetch first line of response and echo it
echo fgets($fp);
// Say line and repeat
fwrite($fp, $choosechar);
fwrite($fp, "#4D90#chat#(a)dolannormal#Dolan#dolannormal#".$lines[array_rand($lines)]."#jud#1#1#0#0#0#0#35#0#1#%");
sleep(120);
// Stuff
echo fgets($fp);
}
fclose($fh);
What i'm exactly trying to achieve here is when the bot detects this (asterisks should be wildcards or something):
#4D90#chat#*#*#*#shut up#*#*#*#*#*#*#*#*#*#*#%
I want the bot to send this data to the server in response using fwrite:
#4D90#chat#(a)dolanangry#Dolan#dolanangry#no#jud#1#1#0#0#0#0#35#0#1#%
How do I do this? Any help is appreciated, thanks.
EDIT: Forgot to mention, i'm using a .bat file to run PHP and the PHP code and not a website.
EDIT2: Made question more specific
$input_string_with_shut_up=$_POST['chat_msg']
$output=str_replace('%shut up%','#4D90#chat#(a)dolanangry#Dolan#dolanangry#no#jud#1#1#0#0#0#0#35#0#1#%',$input_string_with_shut_up)
echo $output;
This might do
I am trying to learn about sockets in PHP and lots of reading has brought me down the route of stream_socket_server().
I got a basic chat working between two terminals in linux using code similar to what is below and was hoping my next step would be to build a chat or a notification system on the web.
What I expected to happen:
The event listener in eventSource.html would listen for an event in the while loop and output the message received from a linux terminal that was running server.php
What is happening:
Everything from the point of view of eventSource.html is working as it should. So if I was to take away the entire purpose of this and just replace the message with a standard string Hello World then this succesfully outputs <li>message:{Hello World}</li> every second.
However once I try and read data from the terminal nothing is appearing except <li>message: {}</li> every second. It is worth noting that when I run server.php it waits for the client, and when I then run eventSource.html it sucessfully connects.
I am misunderstanding how this works? I assumed that every second in the while loop it would look out for data in that stream.
Or am I going down a completely wrong road in terms of learning sockets.
server.php (I load this from the terminal in linux)
<?php
$PORT = 20226; //chat port
$ADDRESS = "localhost"; //adress
$ssock; //server socket
$csock; //chat socket
$uin; //user input file descriptor
$ssock = stream_socket_server("tcp://$ADDRESS:$PORT"); //creating the server sock
echo "Waiting for client...\n";
$csock = stream_socket_accept($ssock); //waiting for the client to connect
//$csock will be used as the chat socket
echo "Connection established\n";
$uin = fopen("php://stdin", "r"); //opening a standart input file stream
$conOpen = true; //we run the read loop until other side closes connection
while($conOpen) { //the read loop
$r = array($csock, $uin); //file streams to select from
$w = NULL; //no streams to write to
$e = NULL; //no special stuff handling
$t = NULL; //no timeout for waiting
if(0 < stream_select($r, $w, $e, $t)) { //if select didn't throw an error
foreach($r as $i => $fd) { //checking every socket in list to see who's ready
if($fd == $uin) { //the stdin is ready for reading
$text = fgets($uin);
fwrite($csock, $text);
}
else { //the socket is ready for reading
$text = fgets($csock);
if($text == "") { //a 0 length string is read -> connection closed
echo "Connection closed by peer\n";
$conOpen = false;
fclose($csock);
break;
}
echo "[Client says] " .$text;
}
}
}
}
client.php gets loaded from eventSource.html below
<?php
date_default_timezone_set("America/New_York");
header("Content-Type: text/event-stream\n\n");
$PORT = 20226; //chat port
$ADDRESS = "localhost"; //adress
$sock = stream_socket_client("tcp://$ADDRESS:$PORT");
$uin = fopen("php://stdin", "r");
while (1) {
$text = fgets($uin);
echo 'data: {'.$text.'}';
echo "\n\n";
ob_end_flush();
flush();
sleep(1);
}
eventSource.html
<script>
var evtSource = new EventSource("client.php");
evtSource.onmessage = function(e) {
var newElement = document.createElement("li");
newElement.innerHTML = "message: " + e.data;
var div = document.getElementById('events');
div.appendChild(newElement);
}
</script>
<div id="events">
</div>
This is what i want to accomplish using php (possibly using exce()?):
telnet to a whois registrar using a program called proxychains:
proxychains telent whois.someregistrar 43
if failed -> try 1 again
feed a domain name to the connection:
somedomainname.com
capture data returned by the registrar to php
I have no experience with shell scripting so how do i capture the event
in which telnet is connected and hangs for input and how do i "feed" it?
Am i totaly off here or is this the right way to go about it?
EDIT: i see python have a good way to handel this using expect
Here is a basic working example.
<?php
$whois = 'whois.isoc.org.il'; // server to connect to for whois
$data = 'drew.co.il'; // query to send to whois server
$errFile = '/tmp/error-output.txt'; // where stderr gets written to
$command = "proxychains telnet $whois 43"; // command to run for making query
// variables to pass to proc_open
$cwd = '/tmp';
$env = null;
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("file", "/tmp/error-output.txt", "a") // stderr is a file to write to
);
// process output goes here
$output = '';
// store return value on failure
$return_value = null;
// open the process
$process = proc_open($command, $descriptorspec, $pipes, $cwd, $env);
if (is_resource($process)) {
echo "Opened process...\n";
$readBuf = '';
// infinite loop until process returns
for(;;) {
usleep(100000); // dont consume too many resources
// TODO: implement a timeout
$stat = proc_get_status($process); // get info on process
if ($stat['running']) { // still running
$read = fread($pipes[1], 4096);
if ($read) {
$readBuf .= $read;
}
// read output to determine if telnet connected successfully
if (strpos($readBuf, "Connected to $whois") !== false) {
// write our query to process and append newline to initiate
fwrite($pipes[0], $data . "\n");
// read the output of the process
$output = stream_get_contents($pipes[1]);
break;
}
} else {
// process finished before we could do anything
$output = stream_get_contents($pipes[1]); // get output of command
$return_value = $stat['exitcode']; // set exit code
break;
}
}
echo "Execution completed.\n";
if ($return_value != null) {
var_dump($return_value, file_get_contents($errFile));
} else {
var_dump($output);
}
// close pipes
fclose($pipes[1]);
fclose($pipes[0]);
// close process
proc_close($process);
} else {
echo 'Failed to open process.';
}
This is meant to be run from the command line, but it doesn't have to be. I tried to comment it fairly well. Basically at the beginning you can set the whois server, and the domain to query.
The script uses proc_open to open a proxychains process that calls telnet. It checks to see if the process was opened successfully, and if so check that its status is running. While its running, it reads the output from telnet into a buffer and looks for the string telnet outputs to indicate we are connected.
Once it detects telnet connected, it writes the data to the process followed by a newline (\n) and then reads the data from the pipe where the telnet data goes. Once that happens it breaks out of the loop and closes the process and handles.
You can view the output from proxychains from the file specified by $errFile. This contains the connection information as well as debug information in the event of a connection failure.
There is probably some additional error checking or process management that may need to be done to make it more robust, but if you put this into a function you should be able to easily call it and check the return value to see if the query was successful.
Hope that gives you a good starting point.
Also check out this answer of mine for another working example of proc_open, this example implements a timeout check so you can bail if the command hasn't completed in a certain amount of time: Creating a PHP Online Grading System on Linux: exec Behavior, Process IDs, and grep
Here is the code that I am using:
if (!($fp = fsockopen('ssl://imap.gmail.com', '993', $errno, $errstr, 15)))
echo "Could not connect to host";
$server_response = fread($fp, 256);
echo $server_response;
fwrite($fp, "C01 CAPABILITY"."\r\n");
while (!feof($fp)) {
echo fgets($fp, 256);
}
I get the first response:
OK Gimap ready for requests from xx.xx.xx.xx v3if9968808ibd.15
but then the page times out. I have searched through stream_set_blocking, stream_set_timeout, stream_select, fread, etc. but could not get it to work. I need to read all the data that the server sends and then proceed with other commands (I would be retrieving emails using imap).
Thanks
Your script is hanging in the while loop at the end. This is because you have used !feof() as the condition for the loop, and the server is not closing the connection. This means the feof() will always return false and the loop will continue forever.
This will not be problem when your write a full implementation, as you will be looking for response codes and can break out of the loop accordingly, for example:
<?php
// Open a socket
if (!($fp = fsockopen('ssl://imap.gmail.com', 993, $errno, $errstr, 15))) {
die("Could not connect to host");
}
// Set timout to 1 second
if (!stream_set_timeout($fp, 1)) die("Could not set timeout");
// Fetch first line of response and echo it
echo fgets($fp);
// Send data to server
echo "Writing data...";
fwrite($fp, "C01 CAPABILITY\r\n");
echo " Done\r\n";
// Keep fetching lines until response code is correct
while ($line = fgets($fp)) {
echo $line;
$line = preg_split('/\s+/', $line, 0, PREG_SPLIT_NO_EMPTY);
$code = $line[0];
if (strtoupper($code) == 'C01') {
break;
}
}
echo "I've finished!";
Your script should be working. In fact, it is working.
See the results below on my pc when I ran your code:
* OK Gimap ready for requests from xx.xx.xx.xx l5if4585958ebb.20
* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 XYZZY SASL-IR AUTH=XOAUTH
C01 OK Thats all she wrote! l5if4585958ebb.20
Since gmail doesn't disconnect you. No end of file occurs. And the page loading simply times out.
In other words: Your script will just keep waiting and waiting until gmail does disconnect, which unfortunately happens after your page load has already timed out.
I want my web server to notify me through a php page when an event occurs at another TCP server, to which the PHP page has successfully connected via a socket. The event is like the TCP server wants to send a message to the web server, etc. Is there any way to accomplish this and/or any references on how to do it?
Sure:
$fp = fsockopen("tcp://example.com", 8888) OR die("could not connect");
while (!feof($fp)) {
$pc = fread($handle, 8192);
if ($pc === false || strlen($pc) == 0)
break;
//a new packet has arrived
//you should collect the read in a variable and wait
//for another packet until you know the message is complete
//(depends on the protocol)
collect_in_result($pc);
if (message_is_complete()) {
if (check_event()) {
//take action
}
}
}