I am trying to connect computer "a" to computer "b" using webrtc and print out the "Click" on computer "b" when the mouse is clicked on computer "a"'s canvas. I already created a working webrtc example where I make a connection between computer "a" and "b" and send messages between them using textboxes(chat).
I know to Attach a click event to the document. When the user clicks anywhere in the document, output "Click" will be displayed.
document.addEventListener("click", function(){
message.value= "Click!";
});
And these are some of the webrtc functions I have, I didnt post all my webRTC functions because I dont wanna make the question longer, it already is.
// a nice wrapper to send data
function send (room, key, data) {
roomRef.child(room).child(key).set(data);
}
// wrapper function to receive data
function recv (room, type, cb) {
roomRef.child(room).child(type).on("value", function (snapshot, key) {
var data = snapshot.val();
if (data) { cb(data); }
});
}
// get references to the document tags
var chatlog = document.getElementById("chatlog");
var message = document.getElementById("message");
function bindEvents () {
channel.onopen = function () { console.log("Channel Open"); }
channel.onmessage = function (e) {
// add the message to the chat log
chatlog.innerHTML += "<div>Peer says: " + e.data + "</div>";
};
}
// send a message the textbox throught
// the data channel for a chat program
function sendMessage () {
var msg = message.value;
channel.send(msg);
message.value = "";
}
My question is I dont know how to connect these two codes together or even if i did, I am not sure if it would work. So my question is how can I click on the canvas on computer "a" and get the textbox to print out "Click" on computer "b".
Thanks for reading
You could look into node.js and socket.io.
With these two you could connect multiple clients together and have a real-time communication between them. Other alternative is to use ajax with php, and make one browser to poll for new commands from server, and other browser to send them to server.
You're mostly there. What you can do is, after setting the message.value property, is call the sendMessage() function. This should trigger the application to send the correct value through the WebRTC Connection.
Related
The websockets server example works as expected. On browser refresh (e.g. S-F5 with chrome), the websocket disconnects, still working as expected. After refresh, the user has to give name again to connect to the server.
How would you capture the refresh-event and keep the user connected? E.g.
Is this doable only on server side or does the client require modifications as well? Haskell examples or links to such would be nice as well as hints on how to do this!
How would you capture the refresh-event...
There isn't really such a thing as a refresh event to detect (I would love to be proved wrong in this!)
... and keep the user connected...
The refresh, or rather, the leaving of the page before loading it again, causes the websocket to disconnect, and (especially if this is the only page on the site that is open), there isn't really much you can do about it.
So the only thing that can be done, is have some sort of auto-reconnect the next time the page loads. A solution that allows this is one where..
when the name is initially entered, the name is saved somewhere in the browser;
when the page reloads, it checks for a previously saved name;
and if it's found, it connects again using that name.
Local storage is one such place to save this, as in the below example, modified from https://github.com/jaspervdj/websockets/tree/master/example to save/retrieve the name from local storage.
$(document).ready(function () {
var savedUser = sessionStorage.getItem("rejoin-user");
if (savedUser) {
joinChat(savedUser);
}
$('#join-form').submit(function () {
joinChat($('#user').val())
});
function joinChat(user) {
sessionStorage.setItem("rejoin-user", user);
$('#warnings').html('');
var ws = createChatSocket();
ws.onopen = function() {
ws.send('Hi! I am ' + user);
};
ws.onmessage = function(event) {
if(event.data.match('^Welcome! Users: ')) {
/* Calculate the list of initial users */
var str = event.data.replace(/^Welcome! Users: /, '');
if(str != "") {
users = str.split(", ");
refreshUsers();
}
$('#join-section').hide();
$('#chat-section').show();
$('#users-section').show();
ws.onmessage = onMessage;
$('#message-form').submit(function () {
var text = $('#text').val();
ws.send(text);
$('#text').val('');
return false;
});
} else {
$('#warnings').append(event.data);
ws.close();
}
};
$('#join').append('Connecting...');
return false;
};
});
... Is this doable only on server side or does the client require modifications as well?
It definitely needs something done in the client to auto-reconnect. The bare bones version above needs no changes to the server, but if you wanted something fancier, like having the cases of initial connect and auto reconnect handled/shown differently somehow, then the server might need to be modified.
I'm trying to re-start the Server sent events after i have stopped it on a button click.
So I stop the event like so:
if(typeof(EventSource)!=="undefined") {
//create an object, passing it the name and location of the server side script
var eSource = new EventSource("mypage.php");
//detect message receipt
eSource.onmessage = function(event) {
//write the received data to the page
document.getElementById("serverData").innerHTML = event.data;
if(event.data !=""){
alert('success');
///Close it here///////////
event.target.close();
}
};
}
else {
document.getElementById("serverData").innerHTML="Whoops! Your browser doesn't receive server-sent events.";
}
Now I need to restart the same SSE like so (if possible at all):
$('#someBtn').click(function(){
//////this is actually my assumption and there is no such a function///
event.target.start();
});
Could someone please advise on this?
Any help would be appreciated.
I noticed that whenever my server is offline, and i switch it back online, it receives a ton of socket events, that have been fired while server was down. ( events that are ... by now outdated ).
Is there a way to stop socket.io from re-emitting the events after they have not received a response for x seconds ?.
When all else fails with open source libraries, you go study the code and see what you can figure out. After spending some time doing that with the socket.io source code...
The crux of the issue seems to be this code that is here in socket.emit():
if (this.connected) {
this.packet(packet);
} else {
this.sendBuffer.push(packet);
}
If the socket is not connected, all data sent via .emit() is buffered in the sendBuffer. Then, when the socket connects again, we see this:
Socket.prototype.onconnect = function(){
this.connected = true;
this.disconnected = false;
this.emit('connect');
this.emitBuffered();
};
Socket.prototype.emitBuffered = function(){
var i;
for (i = 0; i < this.receiveBuffer.length; i++) {
emit.apply(this, this.receiveBuffer[i]);
}
this.receiveBuffer = [];
for (i = 0; i < this.sendBuffer.length; i++) {
this.packet(this.sendBuffer[i]);
}
this.sendBuffer = [];
};
So, this fully explains why it buffers all data sent while the connection is down and then sends it all upon reconnect.
Now, as to how to prevent it from sending this buffered data, here's a theory that I will try to test later tonight when I have more time.
Two things look like they present an opportunity. The socket notifies of the connect event before it sends the buffered data and the sendBuffer is a public property of the socket. So, it looks like you can just do this in the client code (clear the buffer upon connect):
// clear previously buffered data when reconnecting
socket.on('connect', function() {
socket.sendBuffer = [];
});
I just tested it, and it works just fine. I have a client socket that sends an increasing counter message to the server every second. I take the server down for 5 seconds, then when I bring the server back up before adding this code, all the queued up messages arrive on the server. No counts are missed.
When, I then add the three lines of code above, any messages sent while the server is down are not sent to the server (technically, they are cleared from the send buffer before being sent). It works.
FYI, another possibility would be to just not call .emit() when the socket is not connected. So, you could just create your own function or method that would only try to .emit() when the socket is actually connected, thus nothing would ever get into the sendBuffer.
Socket.prototype.emitWhenConnected = function(msg, data) {
if (this.connected) {
return this.emit(msg, data);
} else {
// do nothing?
return this;
}
}
Or, more dangerously, you could override .emit() to make it work this way (not my recommendation).
Volatile events are events that will not be sent if the underlying connection is not ready (a bit like UDP, in terms of reliability).
https://socket.io/docs/v4/emitting-events/#volatile-events
socket.volatile.emit("hello", "might or might not be received");
I'm trying to implement a simple lock using the following code:
Server:
socket.on('lock', function(ressInfo)
{
var lock = false;
if(ressLocks.indexOf(ressInfo.id) === -1)
{
ressLocks.push(ressInfo.id);
lock = true;
}
socket.emit("lock", lock);
});
Client:
this.requestLock = function(ressInfo, callback)
{
if(currentlyOnline)
{
socket.emit("lock", ressInfo);
socket.on("lock", function(lock)
{
// this gets triggered one additional time with each lock
callback(lock);
});
}
else
{
callback(true);
}
}
On the first call I get one callback with true, on the second call I get two callbacks with false, on the third call three, etc.
What is happening here? Why does socket.on get called multiple times?
I can think of two reasons:
Client side:
If you are registering for lock function multiple time
Server side:
As i assume this happens if you are registering multiple times to listen to the events assuming that you are running the socket.on function everytime you recieve events
Heres how you can debug.
Install node-debug
do node-debug "filename"
This will open in debug mode. Now check how many time the socket.on for 'lock' is being registered. I had similar issue. Heres how i solved it.
//check if msgtype is already binded
if (!isMessageTypeBinded(msgType, someKey)) {
// emit ot connection
io.of(someKey).emit(msgType, message)
return
} else {
// apply filter to all connection
var sockets = io.of(someKey).sockets
if (msgType) { // check for message tye
activeMsgConn.push({
"msgType": msgType,
"accessKey": someKey
})
for (index in sockets) {
var socket = sockets[index]
socket.on(msgType, notifyNewMsg(socket))
io.of(someKey).emit(msgType, message)
}
}
}
I am maintianing an array of all the connections made till now.
If a new msg comes, i'll first check if that msg was already binded to the socket and dont add any new namespace. Else i loop thorugh all the socket conneciton and add this handler.
In your case the code need not be same but implementation can be similar.
I have a C# webserver which provides some html/js/css and images to a browser-based client.
I create the page dynamically using javascript, filling images and divs while receiving messages from a websocket C# server.
Sometimes, I receive a message from the websocket and I try to access a resource in the webserver which might be protected.
I have some custom http server events for this (say, 406) because otherwise the browser pops up a dialog box for digest auth login.
I was wondering whether there is a way to channel all 406 events into the same function, say
RegisterHttpEventHandler(406,myFunction);
I guess I could just wrap any request/dynamic load in try and catches, although I'd love a cleaner way of doing this.
EDIT
Here is an example of the workflow which I implemented so far, and which works fine.
// Websocket definition
var conn = new WebSocket('ws://' + addressIP);
// Websocket receiver callback
conn.onmessage = function (event) {
// my messages are json-formatted
var mObj = JSON.parse(event.data);
// check if we have something nice
if(mObj.message == "I have got a nice image for you"){
showImageInANiceDiv(mObj.ImageUrl);
}
};
// Dynamic load image
function showImageInANiceDiv(imgUrl )
{
var imgHtml = wrapUrlInErrorHandler(imgUrl);
$("#imageBox").html(imgHtml);
}
// function to wrap everything in an error handler
function wrapUrlInErrorHandler(Url)
{
return '<img src="' + Url + '" onerror="errorHandler(\''+ Url +'\');"/>';
}
// function to handle errors
function errorHandler(imgUrl)
{
console.log("this guy triggered an error : " + imgUrl);
}
//
the onerror does not tell me what failed, so I have to make an XHR just to find it out. That's a minor thing
You could first try the XHR. If it fails, you know what happened, if it succeeds you can display the image from cache (see also here). And of course you also could make it call some globally-defined custom hooks for special status codes - yet you will need to call that manually, there is no pre-defined global event source.
I'd like to have something like a document.onerror handler to avoid using the wrapUrlInErrorHandler function every time I have to put an image in the page
That's impossible. The error event (MDN, MSDN) does not bubble, it fires directly and only on the <img> element. However, you could get around that ugly wrapUrlInErrorHandler if you didn't use inline event attributes, but (traditional) advanced event handling:
function showImageInANiceDiv(imgUrl) {
var img = new Image();
img.src = imgUrl;
img.onerror = errorHandler; // here
$("#imageBox").empty().append(img);
}
// function to handle errors
function errorHandler(event) {
var img = event.srcElement; // or use the "this" keyword
console.log("this guy triggered an "+event.type+": " + img.src);
}