Creating an hour in Perl using MySql and the Websocket protocol - javascript

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.

Related

WebSocket connection to 'wss://localhost:8000/game' failed ( Symfony, Ratchet )

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

websocket php server wss error

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.

Identify web socket client

I was wondering if anyone could help me with a small issue I have, I am trying to identify each client with the Fleck web sockets library in .NET and with PHP
PHP:
if (isset($_POST['web_socket_username_submit'])) {
$_SESSION['web_socket_username'] = $_POST['web_socket_username'];
header("location: ");
}
if (!isset($_SESSION['web_socket_username'])) {
echo 'You need to select a username before continuing, this username will stick with you untill you clean your cache.<br>';
echo '<form name="webSocketUsernameForm" method="post">';
echo '';
echo '<input type="text" name="web_socket_username" placeholder="Username...">';
echo '<input type="submit" name="web_socket_username_submit" value="Continue">';
echo '</form>';
exit();
}
?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>websocket client</title>
<script type="text/javascript">
var start = function () {
var inc = document.getElementById('incomming');
var wsImpl = window.WebSocket || window.MozWebSocket;
var form = document.getElementById('sendForm');
var input = document.getElementById('sendText');
inc.innerHTML += "connecting to server ..<br/>";
// create a new websocket and connect
window.ws = new wsImpl('ws://localhost:8181/');
// when data is comming from the server, this metod is called
ws.onmessage = function (evt) {
inc.innerHTML += "Emulator: " + evt.data + '<br/>';
};
// when the connection is established, this method is called
ws.onopen = function () {
inc.innerHTML += 'Emulator accepted your connection.<br/>';
};
// when the connection is closed, this method is called
ws.onclose = function () {
inc.innerHTML += 'Emulator closed the connection.<br/>';
}
form.addEventListener('submit', function(e){
e.preventDefault();
var val = input.value;
ws.send(val);
input.value = "";
});
}
window.onload = start;
</script>
</head>
<body>
<form id="sendForm">
<input id="sendText" placeholder="Text to send" />
</form>
<pre id="incomming"></pre>
</body>
</html>
C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WebSockets_Testing
{
using Fleck;
class Program
{
static void Main(string[] args)
{
FleckLog.Level = LogLevel.Debug;
var allSockets = new List<IWebSocketConnection>();
var server = new WebSocketServer("ws://127.0.0.1:8181");
server.Start(socket =>
{
socket.OnOpen = () =>
{
Console.WriteLine("Open!");
allSockets.Add(socket);
};
socket.OnClose = () =>
{
Console.WriteLine("Close!");
allSockets.Remove(socket);
};
socket.OnMessage = message =>
{
Console.WriteLine(message);
allSockets.ToList().ForEach(s => s.Send("You: " + message));
};
});
var input = Console.ReadLine();
while (input != "exit")
{
foreach (var socket in allSockets.ToList())
{
socket.Send(input);
}
input = Console.ReadLine();
}
}
}
}
How would I identify a client without it being spoofed who it is?
One simple way to achieve this is to use socket.ConnectionInfo.Id which returns a unique GUID per socket.

Issues in turning a perl chat program to a web page

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?

websocket server not receiving message

First I built a websocket server using node js and ws module. Then using chrome and firefox, I connect to that server and the connection is successfully established. However, the message I send from browsers does not arrive at the server. I have some code on server to console.log out if message is received. Nothing appears, however when I refresh the browser, the messages I previously sent arrive. The messages did not arrive when sent them but only once I refresh the page. I don't know why. This seems to work in from some other computers but not mine.
Here is the server code:
var WebSocketServer = require('ws').Server
, http = require('http')
, express = require('express')
, app = express();
app.use(express.static(__dirname + '/views'));
var rmi = require('./RMIClient.js');
console.log(rmi);
var server = http.createServer(app);
server.listen(8080);
var wss = new WebSocketServer({server: server});
// from here is the logic codes
var clients = [];
var clientId = 0;
wss.on('connection', function(ws) {
console.log("connection established for client "+ (clients.length+1));
clients.push(ws);
console.log("index is " + clients.indexOf(ws));
clientId += 1;
ws.send("Hello Client: " + clientId);
//
// ws.send("Welcome from AMTT Chatting Server");
ws.on('message',function(data){
console.log('message receieved : '+data);
for(var i = 0;i<clients.length;i++){
clients[i].send(data);
}
});
ws.on('a',function(){
console.log("a event fire from client");
});
ws.on('close', function() {
var index = clients.indexOf(ws);
console.log('stopping client interval '+index);
if (index > -1) {
clients.splice(index, 1);
}
});
});
Here is the client code:
<html>
<script>
//var ws = new WebSocket('ws://localhost:8080/');
var messagearea,inputarea,sendButton;
var connection = new WebSocket(/*'wss://echo.websocket.org');*/'ws://192.168.8.195:8080/');
// When the connection is open, send some data to the server
console.log(connection.readyState);
connection.onopen = function () {
console.log(connection.readyState);
inputarea.disabled = false;
sendButton.disabled = false;
};
// Log errors
connection.onerror = function (error) {
console.log('sorry connection fail:' + JSON.stringify(error));
};
// Log messages from the server
connection.onmessage = function (e) {
messagearea.value = messagearea.value + '\n' + e.data;
console.log('Server: ' + e.data);
};
function sendMessage(){
if(inputarea.value !='')
connection.send(inputarea.value);
inputarea.value = '';
}
</script>
<body>
<textarea rows="15" cols="100" id="messagearea" disabled>
</textarea>
<br/>
<textarea rows="2" cols="90" id="inputarea" required autofocus>
</textarea>
<input type = 'button' value = 'send' id = 'sendbutton' onclick = "sendMessage()"/>
</body>
<script>
messagearea = document.getElementById('messagearea');
messagearea.value = '';
inputarea = document.getElementById('inputarea');
inputarea.value = '';
inputarea.disabled = true;
sendButton = document.getElementById('sendbutton');
sendButton.disabled = true;
</script>
</html>
And again I found that kind of situation when I develop that code in java and deployed in wildfly server. I am lost. I think there is something concerned with my network card. Because that same code work perfectly in my friend's machine.
Does anybody experience this situation ? or any solution?
You can also try the following:
connection.addEventListener("message", function (e) {
processSocketMessage(e);
});
good luck :)

Categories

Resources