Ruslan Posted August 12, 2018 Share Posted August 12, 2018 What I have: 1. Some background threads which work at server and post log information to DB 2. Users which need to see information from log after it added How to provide information to user? I can start timer on Client and every 5 sec check DB - but if will 20 clients - it will be too many requests to DB. Can I start timer at server (1 for all users) and send information to client browser if exists message for this client? How to verify at server which user connected and send message to him? Link to comment Share on other sites More sharing options...
irigsoft Posted August 12, 2018 Share Posted August 12, 2018 try to use TuniThreadTimer , it work on server side. http://forums.unigui.com/index.php?/topic/11015-work-in-background/?hl=threadtimer&do=findComment&comment=58183 Link to comment Share on other sites More sharing options...
Ruslan Posted August 12, 2018 Author Share Posted August 12, 2018 Ideally I need realtime notifications instead timer. Something like this: https://goo.gl/TY1v96(can't attach png image to forum...) is there easy way to send message to UniGUI application and how to send message from UniGUI server to clients? Link to comment Share on other sites More sharing options...
Oliver Morsch Posted August 12, 2018 Share Posted August 12, 2018 You need websockets or long polling or ... Link to comment Share on other sites More sharing options...
Ron Posted August 12, 2018 Share Posted August 12, 2018 There is no websocket component in Unigui yet, but you may be able to use socket.io with node.js: const socketToken = 'mySpecialToken'; procedure TMainForm.myHtmlFrameAjaxEvent(Sender: TComponent; EventName: string; Params: TUniStrings); begin if eventname='doSocketAuth' then begin UniSession.AddJS('socket.emit("authenticate", {token: "' + socketToken + '"});'); end; if eventname='gotData' then begin //myData:=strtointdef(Params.Values['mydata'], 0); //do something with it end; end; //to broadcast some data procedure TMainForm.socketPush(myData:integer); begin UniSession.AddJS('if(socket !== undefined)socket.emit("'+companyName+'", ' + inttostr(myData) + ');'); end; //some JS to run somewhere to setup the socket connection and catch the incoming data if(socket === undefined){ var socket = io('http://127.0.0.1:3000/?company=' + companyName, { reconnection: true, reconnectionDelay: 3000, reconnectionAttempts: 20, forceNew: false, secure: true }); } socket.on('connect', function(){ ajaxRequest(MainForm.myHtmlFrame, ["doSocketAuth"], { }); }); socket.on(companyName, function(data){ ajaxRequest(MainForm.myHtmlFrame, ["gotData"], { mydata : data }); }); //node.js script to run an https socket io server var fs = require('fs'); var https = require('https'); var app = require('express')(); var options = { key: fs.readFileSync('c:/my.key'), cert: fs.readFileSync('c:/my.crt') }; var serverPort = 3000; var server = https.createServer(options, app); var io = require('socket.io')(server); io.on('connection', function(socket){ companyName=socket.handshake.query.company; socket.auth = false; socket.on('authenticate', function(data){ if(data.token == 'mySpecialToken'){ socket.auth = true; } }); setTimeout(function(){ if (!socket.auth) { socket.disconnect('unauthorized'); } }, 1000); socket.on(companyName, function(msg){ if (socket.auth)io.emit(companyName, msg); }); }); server.listen(serverPort, function(){ console.log('Socket.io https server listening on port ' + serverPort); }); You will also need to add socket.io.js to the CustomFiles in servermodule and of course set up the node server. 2 Link to comment Share on other sites More sharing options...
eduardosuruagy Posted August 13, 2018 Share Posted August 13, 2018 There is no websocket component in Unigui yet, but you may be able to use socket.io with node.js: const socketToken = 'mySpecialToken'; procedure TMainForm.myHtmlFrameAjaxEvent(Sender: TComponent; EventName: string; Params: TUniStrings); begin if eventname='doSocketAuth' then begin UniSession.AddJS('socket.emit("authenticate", {token: "' + socketToken + '"});'); end; if eventname='gotData' then begin //myData:=strtointdef(Params.Values['mydata'], 0); //do something with it end; end; //to broadcast some data procedure TMainForm.socketPush(myData:integer); begin UniSession.AddJS('if(socket !== undefined)socket.emit("'+companyName+'", ' + inttostr(myData) + ');'); end; //some JS to run somewhere to setup the socket connection and catch the incoming data if(socket === undefined){ var socket = io('http://127.0.0.1:3000/?company=' + companyName, { reconnection: true, reconnectionDelay: 3000, reconnectionAttempts: 20, forceNew: false, secure: true }); } socket.on('connect', function(){ ajaxRequest(MainForm.myHtmlFrame, ["doSocketAuth"], { }); }); socket.on(companyName, function(data){ ajaxRequest(MainForm.myHtmlFrame, ["gotData"], { mydata : data }); }); //node.js script to run an https socket io server var fs = require('fs'); var https = require('https'); var app = require('express')(); var options = { key: fs.readFileSync('c:/my.key'), cert: fs.readFileSync('c:/my.crt') }; var serverPort = 3000; var server = https.createServer(options, app); var io = require('socket.io')(server); io.on('connection', function(socket){ companyName=socket.handshake.query.company; socket.auth = false; socket.on('authenticate', function(data){ if(data.token == 'mySpecialToken'){ socket.auth = true; } }); setTimeout(function(){ if (!socket.auth) { socket.disconnect('unauthorized'); } }, 1000); socket.on(companyName, function(msg){ if (socket.auth)io.emit(companyName, msg); }); }); server.listen(serverPort, function(){ console.log('Socket.io https server listening on port ' + serverPort); }); You will also need to add socket.io.js to the CustomFiles in servermodule and of course set up the node server. Would you have any examples? Link to comment Share on other sites More sharing options...
Ruslan Posted August 13, 2018 Author Share Posted August 13, 2018 There is no websocket component in Unigui yet, but you may be able to use socket.io with node.js: You will also need to add socket.io.js to the CustomFiles in servermodule and of course set up the node server. Thank you very much! how to use this from EXE file on another server where just only exe-file without unigui? Will I able to connect node.js server from internet? Also I do not quite understand how to check which MainForm shoud show this message and which not (if message only for several active clients from all). It would be greate to have demo application - unigui + separate exe-file with button "send message to unigui client N1". I can pay for this work. Link to comment Share on other sites More sharing options...
Ruslan Posted August 13, 2018 Author Share Posted August 13, 2018 var socket = io('http://127.0.0.1:3000/?company= can I connect in the same way to any socket server, not only node.js? Link to comment Share on other sites More sharing options...
Ron Posted August 13, 2018 Share Posted August 13, 2018 Thank you very much! how to use this from EXE file on another server where just only exe-file without unigui? Will I able to connect node.js server from internet? Also I do not quite understand how to check which MainForm shoud show this message and which not (if message only for several active clients from all). It would be greate to have demo application - unigui + separate exe-file with button "send message to unigui client N1". I can pay for this work. The node.js server listens on a port, and when you open up the firewall it is exposed and will be able to take client connections. The form which should show the message, is the form with the uniHtmlFrame running the JS code. You can process the message in the htmlFrame, as a chat box, or you can send it to the server and show it from there, save it etc. Since the socket.io client is written in JS, which runs only in the browser or in node.js, you have to go through one of these. You can push messages locally into the node.js server in different ways, but that would be the way to go, if you cannot send it from one of the clients. In the example above, the client should of course only connect to localhost when testing, and be pointed to the actual IP or domain of the live server when in production. Link to comment Share on other sites More sharing options...
Ron Posted August 13, 2018 Share Posted August 13, 2018 can I connect in the same way to any socket server, not only node.js? To any socket.io server, yes, but I do not know of any other implementations of socket.io servers than the node.js one. Have not found any windows binaries. Socket.io is not pure websocket protocol, not at all, but it starts there and downgrades to longpolling if the browser do not support websockets. So it provides for greater compatibility across browser versions. Pure websocket components are available for Delphi, from at least one guy. Link to comment Share on other sites More sharing options...
Ruslan Posted August 13, 2018 Author Share Posted August 13, 2018 The node.js server listens on a port, and when you open up the firewall it is exposed and will be able to take client connections. The form which should show the message, is the form with the uniHtmlFrame running the JS code. You can process the message in the htmlFrame, as a chat box, or you can send it to the server and show it from there, save it etc. Since the socket.io client is written in JS, which runs only in the browser or in node.js, you have to go through one of these. You can push messages locally into the node.js server in different ways, but that would be the way to go, if you cannot send it from one of the clients. In the example above, the client should of course only connect to localhost when testing, and be pointed to the actual IP or domain of the live server when in production. looks like I will process which message show to this client on client side? but it will be thousands messages from different client and only 1 from 100 I should show to client. Also it maybe not secure to send all messages to client which should not know any information from this messages. Link to comment Share on other sites More sharing options...
Ron Posted August 13, 2018 Share Posted August 13, 2018 looks like I will process which message show to this client on client side? but it will be thousands messages from different client and only 1 from 100 I should show to client. Also it maybe not secure to send all messages to client which should not know any information from this messages. You can have different channels, like you see I have using the handshake.query parameter, where I use the company name to make sure only those in the same company get it. In addition you can filter out messages according to all kind of criteria before they are shown to the user on the client side. Link to comment Share on other sites More sharing options...
Recommended Posts
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now