I am working on a fun project which requires me to learn message queues and websockets. I am trying to connect browsers via websockets to an instance of rabbitmq using sockjs rather than pure websockets. On rabbit I have activated the plugins for stomp and web_stomp (web_stomp is required when using sockjs).
The problem I am running into is that while the call from the browser seems to be working properly because a very brief connection to Rabbit is made through the webstomp/stomp connection but after 2 or 3 seconds the connection is dropped by Rabbit.
This is confirmed by the rabbitmq logs:
=INFO REPORT==== 11-Jul-2016::23:01:54 ===
accepting STOMP connection (192.168.1.10:49746 -> 192.168.1.100:55674)
=INFO REPORT==== 11-Jul-2016::23:02:02 ===
closing STOMP connection (192.168.1.10:49746 -> 192.168.1.100:55674)
This is the browser code that connects to RabbitMQ via the webstomp plugin:
var url = "http://192.168.1.100:55674/stomp";
var ws = new SockJS(url);
var client = Stomp.over(ws);
var header = {
login: 'test',
passcode: 'test'
};
client.connect(header,
function(){
console.log('Hooray! Connected');
},
function(error){
console.log('Error connecting to WS via stomp:' + JSON.stringify(error));
}
);
Here is the Rabbit config:
[
{rabbitmq_stomp, [{default_user, [{login, "test"},
{passcode, "test"}
]
},
{tcp_listeners, [{"192.168.1.100", 55674}]},
{heartbeat, 0}
]
}
]
I have been over the Rabbit docs a million times but this feels like something simple that I am overlooking.
Resolved. After combing through the logs I realized that web_stomp was listening on port 15674 so I changed the config file to reflect that. I swear I had made that change at some point but it did not seem to make a difference.
One of the late changes I made before sending out my request was to turn off heartbeat. Everything I have read states that sockjs does not support heartbeat and that there were suggestions to turn it off rather than use the default. In addition to turning off heartbeat in the config file I also added this to the browser code:
client.heartbeat.outgoing=0;
client.heartbeat.incoming=0;
Related
Using #golevelup/nestjs-rabbitmq I tried the connection manager to not wait for a connection. According to the readme it can handle reconnections and wait for a connection without crashing the app. However, when I use the connectionInitOptions as stated and set wait to false, I get a connection error. When I don't use it (default behavior setting wait to true) , it connects to the RabbitMQ server. Below are examples importing the RabbitMQModule in a NestJS module.
This works and connects to the RabbitMQ server
RabbitMQModule.forRoot(RabbitMQModule, {
exchanges: [{ type: 'topic', name: 'main' }],
uri: 'amqp://guest:guest#localhost:5672',
}
This doesn't work and won't connect
RabbitMQModule.forRoot(RabbitMQModule, {
exchanges: [{ type: 'topic', name: 'main' }],
uri: 'amqp://guest:guest#localhost:5672',
connectionInitOptions: {
wait: false,
},
With the second option I get the following error:
Error: AMQP connection is not available
at AmqpConnection.publish (/home/xxx/node_modules/#golevelup/nestjs-rabbitmq/src/amqp/connection.ts:424:13)
at BootstrapService.onApplicationBootstrap (/home/xxx/src/bootstrap/bootstrap.service.ts:20:25)
at MapIterator.iteratee (/home/xxx/node_modules/#nestjs/core/hooks/on-app-bootstrap.hook.js:22:43)
at MapIterator.next (/home/xxx/node_modules/iterare/src/map.ts:9:39)
at IteratorWithOperators.next (/home/xxx/node_modules/iterare/src/iterate.ts:19:28)
at Function.from (<anonymous>)
at IteratorWithOperators.toArray (/home/xxx/node_modules/iterare/src/iterate.ts:227:22)
at callOperator (/home/xxx/node_modules/#nestjs/core/hooks/on-app-bootstrap.hook.js:23:10)
at callModuleBootstrapHook (/home/xxx/node_modules/#nestjs/core/hooks/on-app-bootstrap.hook.js:43:23)
at NestApplication.callBootstrapHook (/home/xxx/node_modules/#nestjs/core/nest-application-context.js:199:55)
at NestApplication.init (/home/xxx/node_modules/#nestjs/core/nest-application.js:98:9)
at NestApplication.listen (/home/xxx/node_modules/#nestjs/core/nest-application.js:155:33)
at bootstrap (/home/xxx/src/main.ts:12:3)
The last line (main.ts:12:3) is the app.listen(3000) statement.
There are other options you can set with the connectionInitOptions (reject and timeout) and I've tried the combinations but still no connection.
RabbitMQ is running in a docker container on Linux but that should be no problem. I posted the same question on NestJS discord but got no reply, so hopefully someone on SO has an idea.
Any idea what could be the cause?
Found the problem, I was using the connection in a onApplicationBootstrap method and then the connection is apparently not present yet.
you can wait for connection asynchronously 'onApplicationBootstrap':
or on :
async onModuleInit() {
await this.amqpConnection.managedChannel.waitForConnect(async () => {
await this.assertQueueAndBindToExchange(
transferRequestQueueName,
transferRequestExchangeName,
createdRoutingKey
);
I can not get postman to connect to the server using websockets.
const port =5001;
io.on("connection", (socket) => {
console.log("Client connected",socket.id);
socket.emit("handshake","connected to backend");
socket.on("test", (data)=>{
console.log("test data is:",data);
socket.emit("test", "server heard you!")
});
}
in postman the request address is:
ws://localhost:5001/socket.io/?transport=websocket
the symptoms are: postman says it's connected. but if I try to send anything - it disconnects after a timeout.
if I set the reconnection attempts to 1, it will automatically reconnect when it disconnects...
but I don't think it's actually connecting - because nothing is happening on the server (no new client connected message)
the format of messages I have also experimented with, to no avail.
42["test","i hear you"]
42[test,i hear you]
["test":"i hear you"]
{"test":"I hear you"}
42{"test":"I hear you"}
{"event":"test","data":"I hear you"}
42{"event":"test","data":"I hear you"}
42["event","test","data","I hear you"]
["event","test","data","I hear you"]
I have inspected the console results, and have not found leads there yet. what could I be missing?
You are using socket.io as WebSocket and that does not work because socket.io is not an implementation of websocket.
From official socket.io documentation:
Socket.IO is NOT a WebSocket implementation. Although Socket.IO indeed uses WebSocket as a transport when possible, it adds additional metadata to each packet. That is why a WebSocket client will not be able to successfully connect to a Socket.IO server, and a Socket.IO client will not be able to connect to a plain WebSocket server either.
// WARNING: the client will NOT be able to connect!
const socket = io("ws://echo.websocket.org");
Source: https://socket.io/docs/v4#What-Socket-IO-is-not
Postman v8.10.0 added support for Socket.IO, read more.
Just enter ws://localhost:5001 as the connection URL and hit Connect.
Also, you can configure the client version (default: v3), handshake path (default: /socket.io), and other reconnection configurations in the request settings.
Because you don not add listener. Add listener "handshake" to postman. You will receive message.
This is my code:
io.on('connection', () => {
console.log('user connected');
setInterval(() => {
io.emit('msg', { data: [1, 2, 3] });
}, 5000);
});
Working on socket.io for the first time and trying to get it up and going, I can make the request and I have the server up and going, here is the server in node.
const app = require('express')();
const http = require('http').createServer(app);
const io = require('socket.io')(http);
app.get("/",function (req,res){
res.send("Hello you socket loving bastard!");
});
io.on('connection', socket => {
console.log('user connection', socket);
io.emit('You got someone!', {user: "me"});
});
io.on('close', socket => {
console.log(socket);
});
http.listen(9090, () => {
console.log("Node starting on 9090 for websockets!")
});
Using vue-native-websocket I have this ...
Vue.use(Socket, 'ws://localhost:9090/', {
reconnection: true,
reconnectionAttempts: 5,
reconnectionDelay: 1500
});
The console in the browser says:
build.js?b408:1 WebSocket connection to 'ws://localhost:9090/' failed: Connection closed before receiving a handshake response
The server says nothing in the console at all, however, it will serve the get request
Well... the issue is that I'm using vue-native-websocket Socket.io is NOT a native websocket handler and adds extra header information which was lacking apparently. I switches to just using ws in node and it works fine.
From the Socket.io docs.
Socket.IO is NOT a WebSocket implementation. Although Socket.IO indeed uses WebSocket as a transport when possible, it adds some metadata to each packet: the packet type, the namespace and the packet id when a message acknowledgement is needed. That is why a WebSocket client will not be able to successfully connect to a Socket.IO server, and a Socket.IO client will not be able to connect to a WebSocket server either.
I am able to work with Truffle and Ganache-cli. Have deployed the contract and can play with that using truffle console
truffle(development)>
Voting.deployed().then(function(contractInstance)
{contractInstance.voteForCandidate('Rama').then(function(v)
{console.log(v)})})
undefined
truffle(development)> { tx:
'0xe4f8d00f7732c09df9e832bba0be9f37c3e2f594d3fbb8aba93fcb7faa0f441d',
receipt:
{ transactionHash:
'0xe4f8d00f7732c09df9e832bba0be9f37c3e2f594d3fbb8aba93fcb7faa0f441d',
transactionIndex: 0,
blockHash:
'0x639482c03dba071973c162668903ab98fb6ba4dbd8878e15ec7539b83f0e888f',
blockNumber: 10,
gasUsed: 28387,
cumulativeGasUsed: 28387,
contractAddress: null,
logs: [],
status: '0x01',
logsBloom: ... }
Now when i started a server using "npm run dev". Server started fine but is not connecting with the Blockchain
i am getting the error
Uncaught (in promise) Error: Contract has not been deployed to detected network (network/artifact mismatch)
This is my truffle.js
// Allows us to use ES6 in our migrations and tests.
require('babel-register')
module.exports = {
networks: {
development: {
host: '127.0.0.1',
port: 8545,
network_id: '*', // Match any network id
gas: 1470000
}
}
}
Can you please guide me how i can connect ?
Solve the issue.
issue was at currentProvider, i gave the url of ganache blockchain provider and it worked.
if (typeof web3 !== 'undefined') {
console.warn("Using web3 detected from external source like Metamask")
// Use Mist/MetaMask's provider
// window.web3 = new Web3(web3.currentProvider);
window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:7545"));
} else {
console.warn("No web3 detected. Falling back to http://localhost:8545. You should remove this fallback when you deploy live, as it's inherently insecure. Consider switching to Metamask for development. More info here: http://truffleframework.com/tutorials/truffle-and-metamask");
// fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
}
In your truffle.js, change 8545 to 7545.
Or, in Ganache (GUI), click the gear in the upper right corner and change the port number from 7545 to 8545, then restart. With ganache-cli use -p 8545 option on startup to set 8545 as the port to listen on.
Either way, the mismatch seems to be the issue; these numbers should match. This is a common issue.
Also feel free to check out ethereum.stackexchange.com. If you want your question moved there, you can flag it and leave a message for a moderator to do that.
I've set up a text chat service using the PeerJS implementation of WebRTC's data channel. PeerJS provides a basic signalling server for this purpose, but I have tried to replace that with STUN and TURN servers set up through XirSys (recommended by SimpleWebRTC, another WebRTC library). I haven't deployed to the web yet.
Using Node to serve my static files locally, it will work on a local network (when I am sitting next to the person and they navigate to my ip/port in the browser), but will not work when connecting through different access points on the same network (i.e. at work, on opposite ends of the building).
My hypothesis is that it's hitting a firewall, but still directing traffic to PeerJS' signalling server without falling back to the XirSys STUN and TURN servers I've tried to set up. Here's the code I'm working with:
var stun = {};
var turn1 = {};
var turn2 = {};
$.ajax({
type: "POST",
dataType: "json",
url: "https://api.xirsys.com/getIceServers",
data: {
ident: "myusername",
secret: "long-alphanumeric-secret-key",
domain: "www.adomain.com",
application: "anapp",
room: "aroom",
secure: 1
},
success: function (data, status) {
console.log(data);
stun = data.d.iceServers[0];
turn1 = data.d.iceServers[1];
turn2 = data.d.iceServers[2];
},
async: false
});
var conn;
// Connect to PeerJS, have server assign an ID instead of providing one
var peerID = prompt('What would you like your screen name to be?');
var peer = new Peer(
peerID,
{key: 'mypeerjsserverkey', debug: true},
{
config: {'iceServers': [
{url: stun.url},
{url: turn1.url, credential: turn1.credential, username: turn1.username},
{url: turn2.url, credential: turn2.credential, username: turn2.username}
]
}
});
NOTE: My ident, secret, domain, etc. obviously aren't accurately represented here. I don't think that's where my problem is.
Any thoughts?
If you email us a wireshark capture of your STUN/TURN traffic, we should be able to outline where your problem is. Messages sent over signalling are separate but parallel to WebRTC messages. Therefore, if the app is working but the messages are being sent over signalling, then it's possible the configuration of the application isn't correct.
XirSys provides TURN via UDP over TCP through port 80/443, so if the signalling is connecting and flowing, so should the TURN.
Also, looking at your code, if you pass data.d from your getIceServers success handler to the PeerJS config, that should reduce your code quite a bit :-) The ICE string you're reconstructing doesn't need to be broken down.
Regards,
Lee
XirSys CTO