Hello I'm trying to create a chat application, I googled around and I got some issues on this step. Would appreciate some help...
Server.js
var express = require("express");
var app = express();
var http = require("http").createServer(app);
var io = require("socket.io")(http);
var users = [];
io.on("connection", function (socket) {
console.log("User connected", socket.id);
socket.on("user_connected", function (username) {
users[username] = socket.id;
io.emit("user_connected", username);
});
socket.on("send_message", function (data) {
var socketId = users[data];
io.to(socketId).emit("new_message", data);
console.log(data);
});
});
http.listen(3000, function () {
console.log("Server Started");
});
chat.php
function sendMessage(){
var message = document.getElementById("message").value;
io.emit("send_message", {
sender: sender,
message: message
});
return false;
}
io.on("new_message", function (data) {
console.log(data);
//var html = "";
//html += "<li>" + data.sender + " says: " + data.message + "</li>";
//document.getElementById("messages").innerHTML += html;
});
So my problem is happening in chat.php where my console.log(data) isn't shown, however the data is shown in server.js. Why is this currently not working?
From what you said earlier it's possible that you make it more complicated than it actually is. No need to change anything in chat.php, however instead of creating the variable socketId you could just emit the data immediately like this:
io.on("connection", function (socket) {
console.log("User connected", socket.id);
socket.on("user_connected", function (username) {
users[username] = socket.id;
io.emit("user_connected", username);
});
socket.on("send_message", function (data) {
io.emit("new_message", data);
});
});
Currently I am trying this way:
io.sockets.on('connection', function (client) {
console.log("client connected: " + client.id);
io.sockets.socket(client.id).emit("connected", client.id);
client.on("sendMessage", function (data) {
//send message code
});
});
What i want sendMessage code should be in separate file. So how to do ?
What i have tried :
//in first.js:
var events = require('events');
var em = new events.EventEmitter();
var msg = require('./message.js');
var emitter = msg.em;
io.sockets.on('connection', function (client) {
console.log("client connected: " + client.id);
io.sockets.socket(client.id).emit("connected", client.id);
emitter.emit('sendMessage');
});
//in message.js
client.on("sendMessage", function (data) {
//return "Hello";
//perform db operation
});
whether it is correct or wrong ? Can anyone help?
or is there any new correct way to do ?
You can put the handler in some other file and export it.
Main code:
const sendMessage = require('./send-message');
io.sockets.on('connection', function (client) {
console.log("client connected: " + client.id);
io.sockets.socket(client.id).emit("connected", client.id);
client.on("sendMessage", sendMessage);
});
send-message.js:
module.exports = function (data) {
//send message code
});
I am using the "ws" NodeJS websocket library. Previously I was trying out socket.io; with socket.io I could implement callbacks between the client and server like this:
socket.emit('Data', data, function(data){
console.log(data);
});
socket.on('Data', function(data, callback){
callback('it worked');
});
I have tried to do the same thing using the ws library, but have not had any success. Is it possible, and if so how?
The API is pretty similar and you can do pretty much the same things.
For example on the server side instead of:
s.emit('message', 'message from server');
you use:
s.send('message from server', ()=>{});
To receive it on the client side instead of:
s.on('message', function (m) {
// ...
});
you use:
s.addEventListener('message', function (m) {
// ...
});
And so on.
In this answer I showed example code (both frontend and backend) to demonstrate the difference between Socket.io and WebSocket:
Differences between socket.io and websockets
This is example server code:
var path = require('path');
var app = require('express')();
var ws = require('express-ws')(app);
app.get('/', (req, res) => {
console.error('express connection');
res.sendFile(path.join(__dirname, 'ws.html'));
});
app.ws('/', (s, req) => {
console.error('websocket connection');
for (var t = 0; t < 3; t++)
setTimeout(() => s.send('message from server', ()=>{}), 1000*t);
});
app.listen(3001, () => console.error('listening on http://localhost:3001/'));
console.error('websocket example');
Example browser code:
var l = document.getElementById('l');
var log = function (m) {
var i = document.createElement('li');
i.innerText = new Date().toISOString()+' '+m;
l.appendChild(i);
}
log('opening websocket connection');
var s = new WebSocket('ws://'+window.location.host+'/');
s.addEventListener('error', function (m) { log("error"); });
s.addEventListener('open', function (m) { log("websocket connection open"); });
s.addEventListener('message', function (m) { log(m.data); });
See this for more info.
This can be done with WebSockets-Callback like this
wscb.send({cmd: 'Hello server!'},
function(response){
//do something...
}
)
I am new to node.js and would like to connect to a TCP socket. For this I am using the net module.
My idea was to wrap the connect sequence into a function then on the 'close' event, attempt a reconnection. Not that easy apparently.
function conn() {
client.connect(HOST_PORT, HOST_IP, function() {
startSequence();
})
}
client.on('close', function(e) {
log('info','Connection closed! -> ' + e)
client.destroy();
setTimeout(conn(),1000);
});
So when the remote host is closed, I see my logs comming through, howere what seems to be happening is that as soons as the remote host comes online ALL the previous attempts start to get processed - if that makes sense. If you look at client.connect, there is a function called startSequence that sends some data that "iniates" the connection from the remote server side. When the server goes offline and I start reconnecting all the failed attempts from before seem to have been buffered and are all sent together when the server goes online.
I have tried the code from this Stackoverflow link as well to no avail (Nodejs - getting client socket to try again after 5 sec time out)
client.connect(HOST_PORT, HOST_IP, function() {
pmsStartSequence();
})
// Add a 'close' event handler for the client socket
client.on('close', function(e) {
log('debug','connection closed -> ' + e)
client.setTimeout(10000, function() {
log('debug', 'trying to reconnect')
client.connect(HOST_PORT, HOST_IP, function() {
pmsStartSequence();
})
})
});
Is there any advice on how I can reconnect a socket after failure?
Inspired from the other solutions, I wrote this, it's tested, it works !
It will keep on trying every 5 sec, until connection is made, works if it looses connection too.
/* Client connection */
/* --------------------------------------------------------------------------------- */
const client = new net.Socket()
var intervalConnect = false;
function connect() {
client.connect({
port: 1338,
host: '127.0.0.1'
})
}
function launchIntervalConnect() {
if(false != intervalConnect) return
intervalConnect = setInterval(connect, 5000)
}
function clearIntervalConnect() {
if(false == intervalConnect) return
clearInterval(intervalConnect)
intervalConnect = false
}
client.on('connect', () => {
clearIntervalConnect()
logger('connected to server', 'TCP')
client.write('CLIENT connected');
})
client.on('error', (err) => {
logger(err.code, 'TCP ERROR')
launchIntervalConnect()
})
client.on('close', launchIntervalConnect)
client.on('end', launchIntervalConnect)
connect()
The problem is where you set the on-connect callback.
The doc of socket.connect() says:
connectListener ... will be added as a listener for the 'connect' event once.
By setting it in socket.connect() calls, every time you try reconnecting, one more listener (a one-time one), which calls startSequence(), is attached to that socket. Those listeners will not be fired until reconnection successes, so you got all of them triggered at the same time on a single connect.
One possible solution is separating the connect listener from socket.connect() calls.
client.on('connect', function() {
pmsStartSequence();
});
client.on('close', function(e) {
client.setTimeout(10000, function() {
client.connect(HOST_PORT, HOST_IP);
})
});
client.connect(HOST_PORT, HOST_IP);
My solution:
var parentHOST = '192.168.2.66';
var parentPORT = 9735;
var net = require('net');
var S = require('string');
var parentClient = new net.Socket();
var parentActive = false;
var startParentClient = function () {
parentClient = new net.Socket();
parentActive = false;
parentClient.connect(parentPORT, parentHOST, function() {
console.log('Connected ' + cluster.worker.id + ' to parent server: ' + parentHOST + ':' + parentPORT);
parentActive = true;
});
parentClient.on('error', function() {
parentActive = false;
console.log('Parent connection error');
});
parentClient.on('close', function() {
parentActive = false;
console.log('parent connection closed');
setTimeout(startParentClient(), 4000);
});
}
If is necessary connect:
if (!S(parentHOST).isEmpty() && !S(parentPORT).isEmpty()) {
startParentClient();
}
As mentioned multiple times in the comments, you need to use .removeAllListeners() before trying to reconnect your client to the server in order to avoid having multiple listeners on the same event.
The code below should do the trick
Note that I try to reconnect the client after the close and end events because these two events can be fired in different orders after closing a connection
const net = require("net")
let client = new net.Socket()
function connect() {
console.log("new client")
client.connect(
1337,
"127.0.0.1",
() => {
console.log("Connected")
client.write("Hello, server! Love, Client.")
}
)
client.on("data", data => {
console.log("Received: " + data)
})
client.on("close", () => {
console.log("Connection closed")
reconnect()
})
client.on("end", () => {
console.log("Connection ended")
reconnect()
})
client.on("error", console.error)
}
// function that reconnect the client to the server
reconnect = () => {
setTimeout(() => {
client.removeAllListeners() // the important line that enables you to reopen a connection
connect()
}, 1000)
}
connect()
I use the following code to achieve reconnection with node.js. I am not a Javascript expert so I guess it can be improved but it nevertheless works fine for me.
I hope this could help.
Best.
//----------------------------------------------------------------//
// SocketClient //
//----------------------------------------------------------------//
var net = require('net');
var SocketClient = function(host, port, data_handler, attempt)
{
var node_client;
var attempt_index = (attempt ? attempt : 1);
this.m_node_client = new net.Socket();
node_client = this.m_node_client;
this.m_node_client.on('close', function()
{
var new_wrapper = new SocketClient(host, port, data_handler, attempt_index + 1);
node_client.destroy();
new_wrapper.start();
});
this.m_node_client.on('data', data_handler);
this.m_node_client.on('error', function(data)
{
console.log("Error");
});
this.start = function()
{
this.m_node_client.connect(port, host, function()
{
console.log('Connected ' + attempt_index);
});
};
};
//----------------------------------------------------------------//
// Test //
//----------------------------------------------------------------//
var test_handler = function(data)
{
console.log('TestHandler[' + data + ']');
};
var wrapper = new SocketClient('127.0.0.1', 4000, test_handler);
wrapper.start();
I have tried re-using the same socket connection, by using this:
const s = net.createConnection({port});
s.once('end', () => {
s.connect({port}, () => {
});
});
that didn't work, from the server-side's perspective. If the client connection closes, it seems like a best practice to create a new connection:
const s = net.createConnection({port});
s.once('end', () => {
// create a new connection here
s = net.createConnection(...);
});
sad but true lulz.
Following this:
//
// Simple example of using net.Socket but here we capture the
// right events and attempt to re-establish the connection when
// is is closed either because of an error establishing a
// connection or when the server closes the connection.
//
// Requires
const net = require('net');
// Create socket
const port = 5555;
const host = '127.0.0.1';
const timeout = 1000;
let retrying = false;
// Functions to handle socket events
function makeConnection () {
socket.connect(port, host);
}
function connectEventHandler() {
console.log('connected');
retrying = false;
}
function dataEventHandler() {
console.log('data');
}
function endEventHandler() {
// console.log('end');
}
function timeoutEventHandler() {
// console.log('timeout');
}
function drainEventHandler() {
// console.log('drain');
}
function errorEventHandler() {
// console.log('error');
}
function closeEventHandler () {
// console.log('close');
if (!retrying) {
retrying = true;
console.log('Reconnecting...');
}
setTimeout(makeConnection, timeout);
}
// Create socket and bind callbacks
let socket = new net.Socket();
socket.on('connect', connectEventHandler);
socket.on('data', dataEventHandler);
socket.on('end', endEventHandler);
socket.on('timeout', timeoutEventHandler);
socket.on('drain', drainEventHandler);
socket.on('error', errorEventHandler);
socket.on('close', closeEventHandler);
// Connect
console.log('Connecting to ' + host + ':' + port + '...');
makeConnection();
function createServer() {
const client = new net.Socket();
client.connect(HOST_PORT, HOST_IP, function() {
console.log("Connected");
state = 1 - state;
client.write(state.toString());
});
client.on("data", function(data) {
console.log("Received: " + data);
//client.destroy(); // kill client after server's response
});
client.on("close", function() {
console.log("Connection closed");
//client.connect()
setTimeout(createServer, 2000);
});
}
createServer();
i made an app with socket.io.my problem is when i close node and open again server response count is up.first time 1 resutlset sending but second time 2 and third time 3 and so on? what is the problem
client code is
<script>
var socket = io.connect('http://10.0.0.192:8888');
socket.on('connecting', function () {
console.log('connecting');
});
socket.on('connect', function(s){
console.log('connect');
socket.emit('Baglan');
console.log('emit-Baglan');
socket.on('guncelle',function(data){
console.log(new Date().getMilliseconds());
console.dir(data);
});
});
socket.on('reconnecting', function () {
console.log('reconnecting');
});
socket.on('reconnect', function () {
console.log('reconnect');
});
socket.on('reconnect_failed', function () {
console.log('reconnect_failed');
});
</script>
and server
function getDataForClients() {
var d = new Array();
d.push({records:res});
//console.log(d);
return d;}
function onRequest(request, response) {
var pathname = url.parse(request.url).pathname;
//console.log("Request for " + pathname + " received.");
route(handle, pathname, response, request);
}
server = http.createServer(onRequest);
io = require('socket.io').listen(server);
io.set('log level', 1);
io.sockets.on('connection', function (client) {
//console.log(client);
client.on("Baglan",function(){
//console.log("user connected");
__sockets.push(client);
client.room="weather";
client.records=[];
client.join(client.room);
if(!res)
guncelle(false,client);
else
client.emit("guncelle",getDataForClients());
});
client.on('disconnect', function(){
var i = __sockets.indexOf(client);
__sockets.splice(i,1);
client.leave(client.room);
//console.log("user leave");
});
});
server.listen(8888);
function guncelle(v,c) {
//console.log("update");
var db = mysql.createClient({
user: 'user',
password: '***',
});
db.query('USE '+TEST_DATABASE);
db.query(
"select * from table",
function selectCb(err, results, fields) {
if (err) {
throw err;
}
res = results;
var _data = getDataForClients();
if(v)
io.sockets.emit("guncelle",_data);
else
c.emit("guncelle",_data);
db.end();
}
);
}
there are 5 result between 15 ms.
sorry i cant post image.