I'm using Socket.io to connect a Digital Ocean Node.js server to an iOS Swift app. I've been using the same code with ngrok to build the app and I'm just now switching to Digital Ocean.
The connection event is happening because the Swift app is going through its checks that occur with a connect event (i.e., trying to pull data). However, the callback on the server is not being called so none of the listeners on the server are being called.
I'm doing a regular instantiation of SocketIOClient without any additional parameters:
var socket: SocketIOClient = SocketIOClient(socketURL: URL(string: "https://my_domain.com")!)
The connection function on the server looks like this:
socket.on("connect") {data, ack in }
I have the following server dependencies:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var listeners = require('./listeners');
var bson = require('bson')
var MongoClient = require('mongodb').MongoClient;
var apn = require('apn');
var ObjectID = require('mongodb').ObjectID;
var querystring = require('querystring');
The connection function on the server looks like this:
io.on('connection', function(client) {
console.log("connected")
})
The issue is that nothing is getting printed or happening on the server. The listener is within MongoClient.connect but Mongo is connecting successfully and items are printing within that function, so things are just stopping with the on('connection') function.
Again this was working fine on ngrok.
Any help is appreciated.
Related
I have created chat application using following
Rails
Rabbitmq
nodejs ( with amqplib/callback_api and socket.io )
I have following code in server side
var amqp = require('amqplib/callback_api');
var amqpConn = null;
var app = require('http').createServer()
var io = require('socket.io')(app);
var fs = require('fs');
io.on('connection', function (socket) {
socket.emit('news/1', msg.content.toString());
// socket.disconnect()
});
client side
<%= javascript_include_tag "http://localhost:53597/socket.io/socket.io.js" %>
<script>
var socket = io('http://localhost:53597', {reconnect: true});
socket.on('connect', function () {
console.log('connected');
socket.on('news/1', function (msg) {
console.log('inside coming');
console.log(msg);
});
});
</script>
When I send message, message successfully pushed to queue and messages emitted to socket. The problem is I can get messages when only refresh page and messages are not deleted.
I can't understand what was wrong here ?
Eventually I fixed my issue, the problem is I have placed emit function inside connection event, so that I can get data when only connection established​, connection is established when page load that is the reason I get data when only page load.
I have the following code for emit data
io.sockets.emit('news/1', msg.content.toString());
For IOS I have the following code:
var socket: SocketIOClient!
override func viewDidLoad() {
super.viewDidLoad()
socket = SocketIOClient(socketURL: NSURL(string: "http://localhost:3000")! as URL)
socket.connect()
socket.on("general") { (_, _) in
print(123)
}
}
And in NodeJS, I have this:
io.on('connection', function(socket){
socket.emit('general', "somerandomthing")
});
This works fine as it is. However, then I tried to simulate sending messages to specific clients. I did it by replacing
socket.emit('general', "somerandomthing")
to
socket.to(socket.id).emit('general', "somerandomthing")
It doesnt work anymore If i do that. It probably doesn't make sense, but I can't find any docs that relate specific sockets between an ios client and a server
Instead of:
socket.to(socket.id).emit('general', 'somerandomthing')
You should do this:
io.to(socket.id).emit('general', 'somerandomthing')
Complete Code:
io.on('connection', function(socket){
io.to(socket.id).emit('general', 'somerandomthing')
});
So I built an app that runs a socket server on port 4000. This is the main part of the server (I've removed redundant functions to the question)
var express = require('express');
var config = require('./config');
var https = require('https');
var client = require('./redis/client');
var socketio = require('./data/socket');
var app = express();
app.use(express.static(__dirname + '/static'));
app.set('port', config.PORT);
var server = app.listen(app.get('port'), function() {
console.log('Listening on port ' + server.address().port);
});
var io = socketio.listen(server);
var users = io.on('connection', function(socket) {
var user;
console.log("connected")
}
On the client I have the following (also removed redundant handlers, etc):
var socket: SocketIOClient!
init() {
socket = SocketIOClient(socketURL: "http://localhost:4000")
setupHandlers()
socket.connect()
}
func setupHandlers() {
socket.on("connect") {
data, ack in
print("connected")
self.socket.emit("addUser", self.app.data._id)
}
}
This was working. Then I created a new version of the project and exported this code and it didn't work. So I ran my older version that was working and low and behold that was also not working.
I've been spending days trying to find out why, altering code, testing, blablabla and have come out with nothing.
My only guess now is that maybe an xcode update or something else has changed some hidden file somewhere or something that is preventing connection from the app to the server...
If anyone has any idea of what could be the problem I would be forever grateful!!
I'm using the Bunny gem in Rails and AMQP in Node.js.
Rails is the publisher and the Node.js app is a subscriber.
Code from Rails:
conn = Bunny.new
conn.start
ch = conn.create_channel
x = Bunny::Exchange.new(ch, :direct, "messenger")
q1 = ch.queue("new_messages").bind(x, :routing_key => 'send')
x.publish('hi', :routing_key => 'send')
Code from Node.js:
var amqp = require('amqp');
var connection = amqp.createConnection();
connection.addListener('ready', function(){
var exchange = connection.exchange('messenger');
var queue = connection.queue('new_messages')
queue.bind('messenger', 'send')
queue.subscribe( {ack:true}, function(message){
console.log(message.data.toString())
queue.shift()
});
});
From the management plugin I can see that the Rails code works well, but the code from Node.js doesn't make sense.
Where is my mistake?
The main issue is in how you're attempting to bind your queue to the 'messenger' exchange. You've already used the exchange name to get a reference to the exchange object. Rather than pass in the string name again when binding the queue to the exchange, pass this reference into queue.bind(). Simply change the first queue.bind() argument:
var exchange = connection.exchange('messenger');
var queue = connection.queue('new_messages');
// Use the reference to the exchange object you just received;
// pass it in here instead of the exchange's name
queue.bind(exchange, 'send');
EDIT
Here is a full, working example; just drop in your own connection properties:
var amqp = require('amqp');
var connection = amqp.createConnection({
host: 'my_host',
login: 'my_login',
password: 'my_password',
authMechanism: 'AMQPLAIN',
vhost: 'my_vhost'
});
connection.addListener('ready', function(){
console.log('ready');
var exchange = connection.exchange('messenger');
var queue = connection.queue('new_messages');
queue.bind(exchange, 'send');
// if message successfully received, print message
queue.subscribe( {ack:true}, function(message){
console.log(message.data.toString());
queue.shift();
});
// test by sending a message
exchange.publish('send', 'this is a test message', {}, function() {})
});
Cheers.
Does any one Has every configure nack for the Rails Projects I happen to tried the dummy code
var http = require('http');
var nack = require('nack');
var app = nack.createProcess("/home/viren/myapp/config.ru");
http.createServer(function (req, res) { app.proxy(req, res); }).listen(8124, "127.0.0.1");
but it reported me with the following error
events.js:94
throw new Error('addListener only takes instances of Function');
^ Error: addListener only takes instances of Function
at BufferedRequest. (events.js:94:11)
at Process. (/home/viren/node_modules/nack/lib/process.js:257:21)
at Process.proxy (/home/viren/node_modules/nack/lib/process.js:3:63)
at Server. (/home/viren/simple.proxy.js:7:7)
at Server.emit (events.js:67:17)
at HTTPParser.onIncoming (http.js:1124:12)
at HTTPParser.onHeadersComplete (http.js:108:31)
at Socket.ondata (http.js:1019:22)
at Socket._onReadable (net.js:683:27)
at IOWatcher.onReadable [as callback] (net.js:177:10)
here is my custom rack-file
require "config/environment"
use Rails::Rack::LogTailer
use ActionDispatch::Static
run ActionController::Dispatcher.new
According the source at node_modules/nack/lib/process.js:257 nack is expecting app.proxy to have a signature of app.proxy(req, res, next) with is a common idiom with connect apps. In connect, calling next("some value") is a convention as most apps have a catch all error handler at the bottom of the middleware chain. Since your not using connect, just create your own error handler.
I also created a pull request, so hopefully using next will be optional in the future. https://github.com/josh/nack/pull/25
var http = require('http'); var nack = require('nack');
var app = nack.createProcess("/home/viren/myapp/config.ru");
http.createServer(function (req, res) { app.proxy(req, res, logNackError); }).listen(8124, "127.0.0.1");
function logNackError(err) {
console.log('nack error:', err);
}