I'm developing a really simple MQTT Android client, so I can connect to it with an MQTT Server I created in C# using the MQTTnet library.
I first tested the C# broker with a C# client and Node-RED and it worked just fine.
I also tested the Android Client with CloudMQTT following this tutorial, and it also worked perfectly fine.
But when I tried to connect my Android Client to the C# Server, the Android Client gave me the following error:
Mqtt: Failed to connect to: tcp://localhost:1883 It's not possible to connect to server (32103) - java.net.ConnectException: Connection refused
I'm using BlueStacks as an emulator (I will try to test it in a real Android device asap). I tried to restart the emulator (as said in Paho Mqtt Android connecting to broker fails with (32103)) but it didn't work either.
The code for the Android Client is exactly the same as in the tutorial I mentioned earlier (using the Paho-MQTT library), but changing the serverUri and subscription topic:
final String serverUri = "tcp://localhost:1883";
final String subscriptionTopic = "step/time";
The app only has a TextView where I set the received messages.
As for the C# server, I'm sending a timestamp every 10 seconds. This is my code:
namespace MQTTServerExample
{
class Program
{
static void Main(string[] args)
{
serverAsync();
}
private static async Task serverAsync()
{
// Starting the MQTT Server
var mqttServer = new MqttFactory().CreateMqttServer();
var options = new MqttServerOptions();
//Saving retained application messages
options.Storage = new RetainedMessageHandler();
// Publishing messages
await mqttServer.StartAsync(options);
Console.WriteLine("### SERVER CONNECTED ###");
Console.WriteLine("Press ENTER to exit.");
MqttApplicationMessage message;
#pragma warning disable CS4014
Task.Run(async () =>
{
while (true)
{
message = new MqttApplicationMessageBuilder()
.WithTopic("step/time")
.WithPayload(DateTime.Now.ToString())
.WithExactlyOnceQoS()
.WithRetainFlag(true)
.Build();
await mqttServer.PublishAsync(message);
await Task.Delay(10000); // Every 10 seconds
}
});
#pragma warning restore CS4014
//await mqttServer.PublishAsync(message);
Console.ReadKey();
await mqttServer.StopAsync();
}
}
I'm new to connection protocols and I still don't understand them clearly, so I was hoping you could help me understand this problem.
A java.net.ConnectException: Connection refused exception means that there is no service listening on the host and port you are trying to connect to, for example because the host address or port is wrong, or the service is not started.
Using "tcp://localhost:1883" as server address only works if the server runs on the same machine as the client (i.e. in your case the Android device). You should use the server's name or IP address.
I'm going to guess that your C# broker is only listening on localhost not the external IP address of the machine hosting it.
This would work when ran the C# client on the same machine, but not when you use the external IP address from the Android client.
The other possible option is that you are running a firewall on the broker machine which is stopping the Android client connecting.
Related
Expected Outcome
I'm attempting to make an ASP.NET Core 5.0 application using Kestrel, and I would like to auto port forward the server's port.
Package
I'm currently using the OpenNat.Core package. I have also tried the regular OpenNat and the same issue arises.
Issue
When port forwarding, the program says it has mapped everything correctly and the map even shows when listing all mapped ports on my router. Yet, when I attempt to view its status via CanYouSeeMe.org it returns a timed out error, and I am unable to access the server outside the network.
What I've Tried
I thought that the port mapping might have been opening after the server started, so I manually opened the port and then restarted the Kestrel server.
I made sure that my router supported UPnP
I also have a Synology NAS that I port forward from, and it works just fine.
I had a friend use ZenMap to check the port.
The port shows that it's filtered but not open (and no service was specified).
Code
using Open.Nat;
using System;
using System.Threading;
using System.Threading.Tasks;
...
public static async Task OpenPort(int port, string description)
{
try
{
NatDiscoverer discoverer = new NatDiscoverer();
CancellationTokenSource cts = new CancellationTokenSource(10000);
NatDevice device = await discoverer.DiscoverDeviceAsync(PortMapper.Upnp, cts);
Mapping map = new(Protocol.Tcp, port, port, description);
await device.CreatePortMapAsync(map);
Console.WriteLine($"Created {map}");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
}
Nevermind my firewall was blocking the application. I was able to dynamically add a firewall rule to fix the issue.
I have created C# application that connects to Socket.IO server and send/receive some data. I'm using SocketIoClientDotNet which works when Socket.IO server is on my localhost (windows). But for production, Socket.IO server is on remote Debian Linux server and my app won't connect to it. However I know that remote Socket.IO server is working since I'm also using Express module to run web server which also connects to same Socket.IO only different namespace, and it connects just fine.
I'm using this code to connect to Socket.IO server
Socket socket = IO.Socket("http://someurl:9910/client");
On both servers (local and remote) Socket.IO version is 2.0.4.
EDIT
In node.js code is like this, so i know when somebody is connected:
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io').listen(server, {log: false, serveClient: true});
app.use('/', express.static(__dirname + '/html'));
server.listen(9910);
var ioClient = io.of('/client');
var ioManager = io.of('/manager');
ioClient.on('connection', function (socket) {
debug("Client connected", "Client connected with ID \x1b[36m"+socket.client.id+"\x1b[0m");
}
ioManager.on('connection', function (socket) {
debug("Manager connected", "Manager connected with ID \x1b[36m"+socket.client.id+"\x1b[0m");
}
There is also debug function which is not relevant.
in C# Win Forms app it looks something like this
using Newtonsoft.Json;
using Quobject.SocketIoClientDotNet.Client;
Socket socket;
private void frmMain_Load(object sender, EventArgs e)
{
socketConnect();
}
private void socketConnect()
{
socket = IO.Socket("http://someurl:9910/client");
}
private void socketDisconnect()
{
socket.Disconnect();
}
private void initListeners()
{
socket.On(Socket.EVENT_CONNECT, () =>
{
Console.WriteLine("SOCKET CONNECTED");
});
}
So on my local server I can see debug messages:
06.03.2018. 11:40:12: Client connected; Client connected with ID SknUAgkyMg61QtfUAAAA
But on remote server nothing is happening.
Also there is none C# exceptions except few of my debug messages.
After long time debugging I found that it is a problem in socket.io packet installed using npm.
It appears that some socket.io dependency (not sure which one) is updated and broken since I have installed socket.io packet on my PC a month ago.
Solution was to copy whole socket.io folder from node_modules folder from my PC to the server.
After that everything worked as it should. However many people wont have this issue since it is revealed only on C# to Node.JS socekt.io relation but it is good to know.
I'm porting some TcpListener/TcpClient/etc code to work on UWP. However, the most basic operations which work in a generic windows c# app are failing for me under UWP.
The most basic operation, such as waiting for a TcpClient is failing:
private async Task TestTcpListening()
{
Debug.WriteLine("Creating TcpListneer");
int portNumber = 8554;
TcpListener listener = new TcpListener(IPAddress.Any, portNumber);
listener.Start();
while(true)
{
Debug.WriteLine("Waiting on TcpListener to accept client");
TcpClient client = await listener.AcceptTcpClientAsync();
Debug.WriteLine(string.Format("We got a client! {0}", client));
}
}
If I run this code in a generic windows console application, the "We got a client" bit runs when I tickle the localhost URL. If this runs in a UWP application, it waits forever and the calling app times out.
NOTES:
I've selected the Internet (Client & Server), Internet, and Private Networks capabilities in the Package.appxmanifest
I'm porting an RTSP server, that works fine as a general windows app. As such, the URI I'm using is "rtsp://localhost:8554". When built as a command-line windows app the above code works as expected, when pointing VLC to that URI. The UWP version of the same code waits forever, and VLC times out.
I'm completely new to Windows, so I don't yet know what I don't know.
THOUGHTS:
Do I need to enable "rtsp:" protocol access to the app somehow? I don't want the app to open when an rtsp: url is hit. I just want incoming connections to be handled.
Being new to Windows development, and in particular to UWP, I didn't know about the loopback restriction. For the time being, for testing my RTSP port, using VLC on another computer on the same network resolves my issue above.
I've been trying to setup a client server between a UWP app as the client and a .NET desktop app as the server. I'm using UDP Datagrams as the messaging system between the two.
Here my UWP code to listen for Datagrams on the localhost IP at port 22222:
private async void listenToServer()
{
// Setup UDP Listener
socketListener = new DatagramSocket();
socketListener.MessageReceived += MessageReceived;
await socketListener.BindEndpointAsync(new HostName("127.0.0.1"),"22222");
Debug.WriteLine("Listening: " + socketListener.Information.LocalAddress + " " + socketListener.Information.LocalPort);
}
private async void MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
// Interpret the incoming datagram's entire contents as a string.
uint stringLength = args.GetDataReader().UnconsumedBufferLength;
string receivedMessage = args.GetDataReader().ReadString(stringLength);
Debug.WriteLine("Received " + receivedMessage);
}
Here is my WinForm .NET desktop app to send Datagrams on localhost on port 2222:
public async void sendToClient()
{
// Setup UDP Talker
talker = new UdpClient();
sending_end_point = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 22222);
talker.Connect(sending_end_point);
byte[] send_buffer = Encoding.ASCII.GetBytes("Hello!");
await talker.SendAsync(send_buffer, send_buffer.Length);
}
Here is what I've tried, and what I know from my troubleshooting:
Sending a UDP datagram from UWP to .NET desktop works.
UWP code to send message to .NET desktop over localhost port 11111:
public async void sendToServer()
{
// Connect to the server
socketTalker = new DatagramSocket();
await socketTalker.ConnectAsync(new HostName("127.0.0.1"), "11111");
Debug.WriteLine("Connected: " + socketTalker.Information.RemoteAddress + " " + socketTalker.Information.RemotePort);
// Setup Writer
writer = new DataWriter(socketTalker.OutputStream);
writer.WriteString("Ping!");
await writer.StoreAsync();
writer.DetachStream();
writer.Dispose();
}
.NET desktop code to listen for message from UWP over same IP and port:
private async Task listenToClient()
{
// Setup listener
listener = new UdpClient(11111);
UdpReceiveResult receiveResult = await listener.ReceiveAsync();
Debug.WriteLine(" Received: " + Encoding.ASCII.GetString(receiveResult.Buffer));
}
Sending UDP Datagram from .NET desktop to UWP works across different IPs (2 different computers)
I've tested this by setting the listener and talker IP addresses to the same IP address where the server was running, and it works flawlessly. This lead to research which got me to #3...
Loopback exemption didn't make a difference
Running CheckNetIsolation.exe and the Loopback exemption tool to exempt the UWP app from loopback IP restriction didn't fix this issue. It seems it shouldn't matter, from what I read (Problems with UDP in windows 10. UWP), running in the Visual Studio environment should already be exempt from loopback, but I tried anyways, and not luck.
As much as this sucks, it is blocked by Microsoft by design.
Loopback is permitted only for development purposes. Usage by a
Windows Runtime app installed outside of Visual Studio is not
permitted. Further, a Windows Runtime app can use an IP loopback only
as the target address for a client network request. So a Windows
Runtime app that uses a DatagramSocket or StreamSocketListener to
listen on an IP loopback address is prevented from receiving any
incoming packets.
Source: https://msdn.microsoft.com/en-us/library/windows/apps/hh780593.aspx
The best workaround you can do is to use TCP sockets and connect from the UWP app to your desktop app (not the other way around).
I would like to run a WebSocket server off a worker role in Azure.
This works fine locally on the emulator, but there is a windows firewall prompt the first time the socket server runs.
I'm wondering if anyone would know how to overcome the connection issues with regards to sockets on Azure.
My socket server implementation: OnStart
var server = new WebSocketServer("ws://theappname.cloudapp.net:8080/");
server.Start(socket =>
{
socket.OnOpen = () =>
{
Trace.WriteLine("Connected to " + socket.ConnectionInfo.ClientIpAddress,"Information");
_sockets.Add(socket);
};
});
.... etc
The client implementation:
var socket = new WebSocket("ws://theappname.cloudapp.net:8080");
socket.onopen = function () {
status.html("Connection Opened");
};
socket.onclose = function () {
status.html("Connection Closed");
}
The status changes to closed a few seconds after loading the page.
My endpoint for the worker role below:
WebSocket Input http 8080 <Not Set>
I have now tried to bind to the internal IP address using the following:
RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["WebSocket"].IPEndpoint.ToString();
SOLUTION
For the sake of anyone else facing this when implementing websockets on Azure;
Your firewall probably will deny your connection if not on port 80 or 8080 so create a separate deployment for it.
Endpoint must be set to TCP and not HTTP for the correct firewall rules to be created. (see image)
Just for the sake of trial, why don't you change your Input Endpoit from "http" to "tcp" protocol. And explicitly set the local port to 8080 (which in your case is ). Also you have to keep in mind that Windows Azure Load Balancer would kill any connection that is idleing for more than 60 seconds, so you might want to implement some kind of "ping" solution to keep the connection open.
You might want to take a look at this introductory video that Steve Marx (#smarx) put together on how to run node.js on Windows Azure.