socket.io client receives everything except for one emitter - javascript

I have got client and server socket.io code. Every message is being received except for one handler: when i send the following to the client:
socket.on('loginb', function(login) {
console.log(1);
var a = bedrijven.filter(function(e) {
return e.bedrijfsnaam == login.bnaam && e.pwd == login.pwd;
});
if (a[0] == null||a.length!=1||a==undefined) {
socket.emit('wow', false);
} else {
console.log(2,a);
socket.emit('wow', a[0]);
}
});
everything until "412" will be logged, but the message won't be received. This is how the listener looks at the client side:
socket.on('wow', function(login) {
console.log(26);
});
26 is never getting logged.
The strange thing is: the emitter and the listener are on the same place as other emitters and listeners i have, and work the same. However, this does not work while the rest does.
I also tried replacing socket.emit('wow', a[0]); by socket.emit('wow', 'string'); but no difference.

I found the answer thanks to #jfriend00's comment.
Indeed, the problem was that the client did not receive the socket message because the page refreshed after the submit. This was prevented by adding a return statement at the end of the submit function.

Related

Presence Update event spams

I used presence update for my Discord bot so when me or my friends are getting live on Twitch, the bot would send a message in a channel and console log. But when we go live, the bot does the job, like, it sends the first message then it starts spamming. As you may expect, I don't have the knowledge in js as I am a beginner. So, can someone tell me how to fix this problem or if it can be fixed? Here is my code:
if (!newPresence.activities) return false;
newPresence.activities.forEach(activity => {
if (activity.type == "STREAMING") {
console.log(`${newPresence.user.tag} is streaming at ${activity.url}.`);
};
});
});
And here is the console.log spam:
Mini-Game#8953 is streaming at https://www.twitch.tv/murus.
Mini-Game#8953 is streaming at https://www.twitch.tv/murus.
Mini-Game#8953 is streaming at https://www.twitch.tv/murus.
Mini-Game#8953 is streaming at https://www.twitch.tv/murus.
Add a return after the console.log() inside the forEach
newPresence.activities.forEach((activity,idx,arr) => {
if (activity.type == "STREAMING") {
console.log(`${newPresence.user.tag} is streaming at ${activity.url}.`);
return; //---> ADD this
};
});

Event source in asp.net has response with one turn delay

After hours of googling i found only one sample about event source using for asp.net (Not MVC). Firstly i must say i want to learn it and my final goal is to creating a friendly poker website. SignalR is very very good for my purpose but i do not want to use this because i heard:
SignalR is bad in performance
isn't it?(i hope not). My problem is when server sends response to client it sends the previous text not current:
$("#btnListen").click(function ()
{
var source = new EventSource('SSEHandler.ashx');
source.addEventListener("open", function (event)
{
$('#headerDiv').append('Latest 5 values');
}, false);
source.addEventListener("error", function (event)
{
if (event.eventPhase == EventSource.CLOSED)
{
$('#footerDiv').append('Connection Closed!');
}
}, false);
source.addEventListener("message", function (event)
{
console.log(event.data);
}, false);
});
And this is SSEHandler:
public class SSEHandler : IHttpHandler
{
public bool IsReusable
{
get { return true; }
}
public void ProcessRequest(HttpContext context)
{
HttpResponse Response;
Response = context.Response;
Response.ContentType = "text/event-stream";
Response.Write(string.Format("data: {0}\n\n", "first"));
Response.Flush(); //client has no response received yet
Response.Write(string.Format("data: {0}\n\n", "second"));
Response.Flush(); //now client get "first".
Response.Close();
}
}
After executing this cods client console only have "first". And if i add this to end of SSEHandler:
Response.Write(string.Format("data: {0}\n\n", "third"));
Response.Flush();
In client console we have "first", "Second".
Thanks for reading my long post.
Its been a while since you asked the question, but after struggling with this for a while myself I found a workaround I thought could be useful to share for others having the same issue.
Simply adding a comment (line that starts with colon) after each event will make the events appear when they should.
Response.Write("data: first\n\n")
Response.Write(":comment\n")
Response.Write("data: second\n\n")
Response.Write(":comment\n")
Note: The problem is more apparent when working with events that comes dynamically, since at that point the first event wont produce anything on the client, then when the second event hits, the first is displayed in the client. And this goes on with second and third etc..

socket.io stop re-emitting event after x seconds/first failed attempt to get a response

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");

Socket.io: receive event triggering multiple times

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.

Server-Sent Events using Poco::Net::HTTPRequestHandler

I'm trying to "stream" data to an HTML5 page using server-sent events.
This tutorial http://www.html5rocks.com/en/tutorials/eventsource/basics/ was quite helpful to get the client side working.
But for the server side, I'm doing something similar to the HTTPServer example in http://pocoproject.org/slides/200-Network.pdf
The html5rocks.com tutorial gave me the following idea for the request handler's code:
void MyRequestHandler::handleRequest (HTTPServerRequest &req, HTTPServerResponse &resp)
{
resp.setStatus(HTTPResponse::HTTP_OK);
resp.add("Content-Type", "text/event-stream");
resp.add("Cache-Control", "no-cache");
ostream& out = resp.send();
while (out.good())
{
out << "data: " << "some data" << "\n\n";
out.flush();
Poco::Thread::sleep(500)
}
}
and the HTML5 page's source:
<!DOCTYPE html>
<html>
<head>
<title>HTLM5Application</title>
</head>
<body>
<p id="demo">hello</p>
<script>
var msgCounter = 0;
var source;
var data;
if(typeof(EventSource) !== "undefined")
{
source = new EventSource('/stream');
document.getElementById("demo").innerHTML = "Event source created";
}
else
{
document.getElementById("demo").innerHTML = "Are you using IE ?";
}
source.addEventListener('message', function(e)
{
msgCounter++;
document.getElementById("demo").innerHTML = "Message received (" + msgCounter + ") !<br/>"+ e.data;
}, false);
</script>
</body>
</html>
The good thing is that, when opening the html page, the data gets streamed and I get a correct outpout (the text between the tag gets updated as expected.
The problem is that when I close the page in the browser, the POCO program crashes, and I get the following message in the console:
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
Process returned 3 (0x3) execution time : 22.234 s
Press any key to continue.
(I'm using Code::Blocks, that's why the return value and the execution time are displayed)
Event when I put the while() loop between try{ }catch(...){} the program still crashes without entering the catch (same thing happens when I put the entire main()'s content in between try/catch )
The main program contains only these instructions:
int main(int argc, char* argv[])
{
MyServerApp myServer;
myServer.run(argc, argv);
return 0;
}
I want to know what could cause that crash and how I can fix it, please.
Thank you in advance for your help :)
For anyone interested, I was able to deal with this issue by registering my own error handler that simply ignores the exception thrown when an SSE-client disconnects:
#include <Poco\ErrorHandler.h>
// Other includes, using namespace..., etc.
class ServerErrorHandler : public ErrorHandler
{
public:
void exception(const Exception& e)
{
// Ignore an exception that's thrown when an SSE connection is closed.
//
// Info: When the server is handling an SSE request, it keeps a persistent connection through a forever loop.
// In order to handle when a client disconnects, the request handler must detect such an event. Alas, this
// is not possible with the current request handler in Poco (we only have 2 params: request and response).
// The only hack for now is to simply ignore the exception generated when the client disconnects :(
//
if (string(e.className()).find("ConnectionAbortedException") == string::npos)
poco_debugger_msg(e.what());
}
};
class ServerApp : public ServerApplication
{
protected:
int main(const vector<string>& args)
{
// Create and register our error handler
ServerErrorHandler error_handler;
ErrorHandler::set(&error_handler);
// Normal server code, for example:
HTTPServer server(new RequestHandlerFactory, 80, new HTTPServerParams);
server.start();
waitForTerminationRequest();
server.stop();
return Application::EXIT_OK;
}
};
POCO_SERVER_MAIN(ServerApp);
However, I must say that this is an ugly hack. Moreover, the error handler is global to the application which makes it even less desirable as a solution. The correct way would be detect the disconnection and handle it. For that Poco must pass the SocketStream to the request handler.
You can change your code to catch Poco Exceptions:
try {
MyServerApp myServer;
return myServer.run(argc, argv);
}catch(const Poco::Exception& ex) {
std::cout << ex.displayText() << std::endl;
return Poco::Util::Application::EXIT_SOFTWARE;
}

Categories

Resources