I have the below server and client codes in perl for chatting.
server code
#!C:\strawberry\perl\bin\perl.exe
use strict;
use warnings;
use IO::Socket::INET;
use IO::Select;
$| = 1;
my $serv = IO::Socket::INET->new(
LocalAddr => '0.0.0.0',
LocalPort => '5000',
Reuse => 1,
Listen => 1,
);
$serv or die "$!";
print 'server up...';
my $sel = IO::Select->new($serv); #initializing IO::Select with an IO::Handle / Socket
print "\nAwaiting Connections\n";
while(1){
if(my #ready = $sel->can_read(0)){ #polls the IO::Select object for IO::Handles / Sockets that can be read from
while(my $sock = shift(#ready)){
if($sock == $serv){
my $client = $sock->accept();
my $paddr = $client->peeraddr();
my $pport = $client->peerport();
print "New connection from $paddr on $pport";
$sel->add($client);
#for read/writability with can_read and can_write
}
else{
$sock->recv(my $data, 1024) or die "$!";
if($data){
for my $clients ($sel->can_write(0)){
if($clients == $serv){next}
print $clients $data;
}
}
}
}
}
}
#client code#
#!C:\strawberry\perl\bin\perl.exe
use CGI;
my $q = new CGI;
use strict;
use warnings;
use IO::Socket::INET;
use threads;
use IO::Select;
$| = 1;
my $sock = IO::Socket::INET->new("localhost:5000");
$sock or die "$!";
my $sel = IO::Select->new($sock);
print $q->header;
my $line = $q->param("login");
print $line;
print " <META http-equiv=\"refresh\" > ";
print "Connected to Socket ". $sock->peeraddr().":" . $sock->peerport() . "\n";
# content="URL=ipl7.pl"
#This creates a thread that will be used to take info from STDIN and send it out
#through the socket.
threads->create(
sub {
# while(1){
chomp($line);
for my $out (my #ready = $sel->can_write(0)){
print $out $line;
# }
}
}
);
# while(1){
if(my #ready = $sel->can_read(0)){
for my $sock(#ready){
$sock->recv(my $data, 1024) or die $!;
print "$data","\n" if $data;
# }
}
}
chat web page
<input type="text" id="txtSearch" onkeypress="searchKeyPress(event);" />
<input type="hidden" id="login" name="login" onclick="verifyLoginRequest();return true;" />
<div id="id_id"> </div>
<script type="text/javascript">
function searchKeyPress(e)
{
// look for window.event in case event isn't passed in
// if (typeof e == 'undefined' && window.event) { e = window.event; }
if (e.keyCode == 13)
{
document.getElementById('login').click();
document.getElementById('txtSearch').value="";
}
}
</script>
<script type="text/javascript">
function createRequestObject() {
var req;
if (window.XMLHttpRequest) { // Firefox, Safari, Opera...
req = new XMLHttpRequest();
} else if (window.ActiveXObject) { // Internet Explorer 5+
req = new ActiveXObject("Microsoft.XMLHTTP");
} else {
// error creating the request object,
// (maybe an old browser is being used?)
alert('There was a problem creating the XMLHttpRequest object');
req = '';
}
return req;
}
// Make the XMLHttpRequest object
var http_login = createRequestObject();
function verifyLoginRequest() {
var login = document.getElementById("txtSearch").value;
if ( login ) {
var url = 'dd.pl?login='+login;
http_login.open('get', url );
http_login.onreadystatechange = handleLoginResponse;
http_login.send(null);
}
}
function handleLoginResponse() {
if(http_login.readyState == 4 && http_login.status == 200){
var response = http_login.responseText; // Text returned FROM perl script
if(response) { // UPDATE ajaxTest content
document.getElementById("id_id").innerHTML = response;
}
}
}
</script>
the following error is displayed
Perl exited with active threads:
\t1 running and unjoined
\t0 finished and unjoined,
\t0 running and detached
What is this error about and how to clear this error?
Related
I am trying to make a real time chat using symfony 6, ratchet and javascript however I can't connect to the localhost even though the URL seems to right one when I look at it in the console.
Here is my commander
<?php
namespace App\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Ratchet\App;
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use App\Websocket\MessageHandler;
use App\Sockets\LiveChat;
class SocketCommand extends Command
{
protected function configure()
{
$this->setName('sockets:start-chat')
->setHelp("Starts the chat socket demo")
->setDescription('Starts the chat socket demo');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
// $server = IoServer::factory(
// new HttpServer(
// new WsServer(
// new LiveChat()
// )
// ),
// 8000
// );
$output->writeln([
'Chat socket',
'============',
'Starting chat, open your browser.',
]);
//$app = new App('localhost', 8000, '127.0.0.1');
$app = new \Ratchet\App('127.0.0.1', 8000, '0.0.0.0');
$app->route('/game', new LiveChat);
$app->run();
}
}
Here is the code that inits the websocket
<?php
namespace App\Sockets;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use SplObjectStorage;
class LiveChat implements MessageComponentInterface
{
protected $clients;
public function __construct()
{
$this->clients = new SplObjectStorage;
}
public function onOpen(ConnectionInterface $conn)
{
$this->clients->attach($conn);
echo "New connection! ({$conn->resourceId})\n";
}
public function onMessage(ConnectionInterface $from, $msg)
{
$numRecv = count($this->clients) - 1;
echo sprintf('Connection %d sending message "%s" to %d other connection%s' . "\n", $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');
foreach ($this->clients as $client) {
if ($from !== $client) {
// The sender is not the receiver, send to each client connected
$client->send($msg);
}
}
}
public function onClose(ConnectionInterface $conn)
{
// The connection is closed, remove it, as we can no longer send it messages
$this->clients->detach($conn);
echo "Connection {$conn->resourceId} has disconnected\n";
}
public function onError(ConnectionInterface $conn, \Exception $e)
{
echo "An error has occurred: {$e->getMessage()}\n";
w $conn->close();
}
}
and last but not least the javascript to connect to the websocket
var clientInformation = {
username: new Date().getTime().toString()
// You can add more information in a static object
};
var conn = new WebSocket('wss://localhost:8000/game');
console.log(conn);
conn.onopen = function(e) {
console.info("Connection established succesfully");
};
conn.onmessage = function(e) {
var data = JSON.parse(e.data);
Chat.appendMessage(data.username, data.message);
console.log(data);
};
conn.onerror = function(e) {
alert("Error: something went wrong with the socket.");
console.error(e);
};
document.getElementById("form-submit").addEventListener("click", function() {
var msg = document.getElementById("form-message").value;
if (!msg) {
alert("Please send something on the chat");
}
Chat.sendMessage(msg);
document.getElementById("form-message").value = "";
}, false);
var Chat = {
appendMessage: function(username, message) {
var from;
if (username == clientInformation.username) {
from = "me";
} else {
from = clientInformation.username;
}
var ul = document.getElementById("chat-list");
var li = document.createElement("li");
li.appendChild(document.createTextNode(from + " : " + message));
ul.appendChild(li);
},
sendMessage: function(text) {
clientInformation.message = text;
conn.send(JSON.stringify(clientInformation));
this.appendMessage(clientInformation.username, clientInformation.message);
}
};
Any help would be really appreciated,
Thank you !
I think, you should use WS with localhost and WSS for secured WS using the assigned IP not localhost.
var conn = new WebSocket('ws://localhost:8000/game'); // try changing WSS -> WS
Good afternoon, I'm writing chat in Perl using Mysql and the Websocket protocol.
I am using the AnyEvent module and Protocol :: WebSocket.
I understand that it would be better to use Mojo or Node.js for this, but in my case it needs to be that way.
I receive data from Websocket, reverse and connect. The data entered in the input field also fits into the database.
My problem is that how can I now output this data to the web interface in real time.
#!/usr/bin/env perl
use strict;
use warnings;
use AnyEvent;
use AnyEvent::Handle;
use AnyEvent::DBI::MySQL;
use AnyEvent::Socket;
use Protocol::WebSocket::Handshake::Server;
use Protocol::WebSocket::Frame;
my $dbh = AnyEvent::DBI::MySQL->connect("DBI:mysql:chat:localhost", "admin", "admin",
{
mysql_enable_utf8 => 1,
PrintError => 0,
}) or die;
my $cv = AnyEvent->condvar;
my $hdl;
my $sth;
AnyEvent::Socket::tcp_server undef, 3000, sub {
my ($clsock, $host, $port) = #_;
my $hs = Protocol::WebSocket::Handshake::Server->new;
my $frame = Protocol::WebSocket::Frame->new;
$hdl = AnyEvent::Handle->new(fh => $clsock);
$hdl->on_read(
sub {
my $hdl = shift;
my $chunk = $hdl->{rbuf};
$hdl->{rbuf} = undef;
if (!$hs->is_done) {
$hs->parse($chunk);
if ($hs->is_done) {
$hdl->push_write($hs->to_string);
return;
}
}
$frame->append($chunk);
my $message = $frame->next;
if ($message eq ""){
$message = undef;
} else {
$sth = $dbh->do("INSERT INTO web_chat VALUES('$message')", { async => 0 });
}
my $ary_ref = $dbh->selectcol_arrayref("SELECT text FROM web_chat");
}
);
};
$cv->wait;
1;
Client is not written in Javascript
<!doctype html>
<form name="publish">
<input type="text" name="message" maxlength="50"/>
<input type="submit" value="Send"/>
</form>
<div id="messages"></div>
<script>
let socket = new WebSocket('ws://192.168.1.1:3000/websocket/');
// отправка сообщения из формы
document.forms.publish.onsubmit = function() {
let outgoingMessage = this.message.value;
socket.send(outgoingMessage);
return false;
};
socket.onopen = function () {
console.log("Websocket Connection");
};
socket.onerror = function () {
console.log("Error websocket connection ");
}
// прослушка входящих сообщений
socket.onmessage = function(event) {
let incomingMessage = event.data;
showMessage(incomingMessage);
};
socket.onclose = event => console.log(`Closed ${event.code}`);
// отображение информации в div#messages
function showMessage(message) {
let messageElem = document.createElement('div');
messageElem.textContent = message;
document.getElementById('messages').prepend(messageElem);
}
</script>
May I suggest Mojolicious and Mojo::Mysql for this?
Protocol::WebSocket is pretty “bare-bones” and doesn’t handle a lot of the protocol details like ping/pong.
I 'm trying to execute commands (wp cli) with xhr.
My problem is when i call my file deploy.php with the javascript.
Without JS call the script works, the flush is immediate.
When i call deploy.php in a XmlHttpRequest, the response wait until the end of the php execution.
I try different commands (grep / wp cli / find) but the result is the same.
I work on WSL Debian + Chrome.
// PHP
public function liveExecuteCommand($cmd, $ajax = false)
{
ob_start();
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("file", "error-output.txt", "a")
);
$output = '';
$process = proc_open($cmd, $descriptorspec, $pipes);
if (is_resource($process)) {
fwrite($pipes[0], '<?php print_r($_ENV); ?>');
fclose($pipes[0]);
while ($s = fread($pipes[1], 8192)) {
$output .= $s;
print $s;
$this->doFlush();
}
fclose($pipes[1]);
$return_value = proc_close($process);
//echo "La commande a retourné $return_value\n";
}
if ($ajax == false) {
return $output;
}
}
$obj->liveExecuteCommand($cmd, true);
die();
// JS
function getLiveStream() {
var ajax = new XMLHttpRequest();
var url = 'https://www.monsite.local/deploy.php';
ajax.open('GET', url, true);
ajax.onprogress = function() {
document.getElementById("xhr_cmd_result").innerHTML = ajax.responseText;
console.log('onprogress');
}
ajax.onload = function() {
console.log('onload');
}
ajax.onreadystatechange = function() {
document.getElementById("xhr_cmd_result").innerHTML = ajax.responseText;
console.log('statechange');
}
ajax.send();
}
window.addEventListener('DOMContentLoaded', (event_loaded) => {
document.getElementById("xhr_cmd").onclick = getLiveStream;
});
In the Google chrome console, the result display all status directly (after 1 min), like the php result.
statechange
onprogress
statechange
onprogress
statechange
onprogress
statechange
onload
I would like have a console.log every time that the flush is called.
No problem when i execute the php file in the browser, the problem is certainly in the javascript.
How do I solve the problem?
Let me explain you in simple words.
Javascript's XMLHttpRequest(AJAX) call will request to server. It will only waits for response from server(final output from your php page), irrespective to internal process of server.
I have this code on http://example.com/push8/index.html
index.html
<script src="websocket.js"></script>
<script>
var Server;
function log(text) {
$log = $('#log');
//Add text to log
$log.append(($log.val()?"\n":'')+text);
//Autoscroll
$log[0].scrollTop = $log[0].scrollHeight - $log[0].clientHeight;
}
function send(text) {
Server.send('message', text);
}
$(document).ready(function() {
log('Conectando...');
Server = new FancyWebSocket('wss://myip:port'); //or ws if I use HTTP
$('#message').keypress(function(e) {
if ( e.keyCode == 13 && this.value ) {
log( 'You: ' + this.value );
send( this.value );
$(this).val('');
}
});
//Let the user know we're connected
Server.bind('open', function(){
log( "Conectado." );
});
//OH NOES! Disconnection occurred.
Server.bind('close', function(data){
log( "Desconectado." );
});
//Log any messages sent from server
Server.bind('message', function(payload){
log( payload );
});
Server.connect();
});
</script>
websocket.js
var WebSocket = function(url)
{
var callbacks = {};
var ws_url = url;
var conn;
this.bind = function(event_name, callback){
callbacks[event_name] = callbacks[event_name] || [];
callbacks[event_name].push(callback);
return this;// chainable
};
this.send = function(event_name, event_data){
this.conn.send( event_data );
return this;
};
this.connect = function() {
if ( typeof(MozWebSocket) == 'function' )
this.conn = new MozWebSocket(url);
else
this.conn = new WebSocket(url);
// dispatch to the right handlers
this.conn.onmessage = function(evt){
dispatch('message', evt.data);
};
this.conn.onclose = function(){dispatch('close',null)}
this.conn.onopen = function(){dispatch('open',null)}
};
this.disconnect = function() {
this.conn.close();
};
var dispatch = function(event_name, message){
var chain = callbacks[event_name];
if(typeof chain == 'undefined') return; // no callbacks for this event
for(var i = 0; i < chain.length; i++){
chain[i]( message )
}
}
};
and the server.php
<?php
// prevent the server from timing out
set_time_limit(0);
// include the web sockets server script (the server is started at the far bottom of this file)
require 'class.PHPWebSocket.php';
// when a client sends data to the server
function wsOnMessage($clientID, $message, $messageLength, $binary) {
global $Server;
$ip = long2ip( $Server->wsClients[$clientID][6] );
if ($messageLength == 0){/*check if message length is 0*/
$Server->wsClose($clientID);
return;}
foreach ($Server->wsClients as $id => $client){
if ($id != $clientID){$Server->wsSend($id, "Visita $clientID($ip): \"$message\" (tu id es: $id)");}}
}
// when a client connects
function wsOnOpen($clientID){
global $Server;
$ip=long2ip($Server->wsClients[$clientID][6]);
$Server->log( "$ip ($clientID) se ha conectado." );
}
// when a client closes or lost connection
function wsOnClose($clientID, $status) {
global $Server;
$ip=long2ip($Server->wsClients[$clientID][6]);
$Server->log("$ip ($clientID) se ha desconectado.");
}
// start the server
$Server = new PHPWebSocket();
$Server->bind('message', 'wsOnMessage');
$Server->bind('open', 'wsOnOpen');
$Server->bind('close', 'wsOnClose');
$Server->wsStartServer('myip', 'port');
?>
This code works perfectly when I use a HTTP connection but when I use the HTTPS doesn't work. The error is:
WebSocket connection to 'wss://myip:port/' failed: Error in connection establishment: net::ERR_CONNECTION_CLOSED
I tried different ways like:
on apache config, I added ProxyPass "/push8" "ws://localhost:port"
I installed engintron and I added the same.
It didn't work...
Note: I use the default Cpanel config and Centos.
I don't know if you've solved this yet. But for anyone looking for a solution, this is what I had to do. I'm running Apache2 on Debian, PHP 7.
Make sure that the php proxy_wstunnel_module is installed.
In the file proxy_wstunnel.load inside the /etc/apache2/mods-available folder. Add the line you added to the php.ini file. For me it did not work adding it to the php.ini file.
ProxyPass "/push8" "ws://localhost:port/"
service php7.0-fpm stop
service php7.0-fpm start
Restart Apache and your websocket should connect.
I am working on a php/mysql application, I am trying to collect javascript errors to the database using window.onerror, where inside that function I make an ajax request to a php script that will log the errors into the database. However, when I tested it there are supposed to be 13 errors logged, but only one get inserted into the database. All the 13 ajax requests return 200 OK, is this happening because ajax is just simply too fast for the mysql query to process anything. I tried using set timeout on the send request but it doesnt seem to work.
Here is my code:
window.onerror = function(msg, url, line)
{
function createXHR()
{
try { return new XMLHttpRequest(); } catch(e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e) {}
try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) {}
try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) {}
return null;
}
function sendRequest(url, payload)
{
var xhr = createXHR();
if (xhr)
{
xhr.open("POST",url,true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function(){
if (xhr.readyState == 4 && xhr.status == 200){
console.log(xhr.responseText);
}
};
xhr.send(payload);
}
}
function encodeValue(val)
{
var encodedVal;
if (!encodeURIComponent)
{
encodedVal = escape(val);
/* fix the omissions */
encodedVal = encodedVal.replace(/#/g, '%40');
encodedVal = encodedVal.replace(/\//g, '%2F');
encodedVal = encodedVal.replace(/\+/g, '%2B');
}
else
{
encodedVal = encodeURIComponent(val);
/* fix the omissions */
encodedVal = encodedVal.replace(/~/g, '%7E');
encodedVal = encodedVal.replace(/!/g, '%21');
encodedVal = encodedVal.replace(/\(/g, '%28');
encodedVal = encodedVal.replace(/\)/g, '%29');
encodedVal = encodedVal.replace(/'/g, '%27');
}
/* clean up the spaces and return */
return encodedVal.replace(/\%20/g,'+');
}
if (window.XMLHttpRequest) {
var master = "llesmana#ucsd.edu";
var payload = "msg=" + encodeValue(msg) + '&url=' + encodeValue(url) + "&line=" + encodeValue(line) + "&master=" + encodeValue(master);
var url_req = "http://104.131.199.129:83/php/log_error.php";
sendRequest(url_req, payload);
return true;
}
return false;
}
PHP:
<?php
/**
* Created by PhpStorm.
* User: xxvii27
* Date: 9/2/14
* Time: 12:30 PM
*/
/* Helper functions */
function gpc($name)
{
if (isset($_GET[$name]))
return $_GET[$name];
else if (isset($_POST[$name]))
return $_POST[$name];
else if (isset($_COOKIE[$name]))
return $_COOKIE[$name];
else
return "";
}
//Database Connection
function connectDB (){
define('DB_HOST', 'localhost');
define('DB_NAME', 'userinfo');
define('DB_USER','root');
define('DB_PASSWORD','ohanajumba');
$con=mysqli_connect(DB_HOST,DB_USER,DB_PASSWORD, DB_NAME) or die("Failed to connect to MySQL: " . mysql_error() );
return $con;
}
function logError($occured, $name, $line, $master, $url, $db){
$command="INSERT INTO errors (id, occured, name, url, line, master) VALUES (NULL, '$occured', '$name', '$url','$line', '$master')";
mysqli_query($db, $command) or die(mysql_error());
}
$db = connectDB();
$message = htmlentities(substr(urldecode(gpc("msg")),0,1024));
$url = htmlentities(substr(urldecode(gpc("url")),0,1024));
$line = htmlentities(substr(urldecode(gpc("line")),0,1024));
$master = htmlentities(substr(urldecode(gpc("master")),0,1024));
$date = date('Y-m-d G:i:s', time());
logError($date, $message, $line, $master, $url, $db);
mysqli_close($db);
Also, I have checked all the sent data through the request and all of them have been received properly by the script, any help would be appreciated.
I solved it , apparently I forgot to use mysqli_real_escape_string().