Connection not working from Android to UWP on desktop - ZeroMq (NetMq) - sockets

I tried some examples of ZMQ on C++,C# and Python. I am trying to have Request-Reply pattern to connect Android device to PC running UWP with Xamarin forms.
Below is the Requestor code:
public void HelloWorld()
{
var timer = new Timer(60000);
timer.Start();
timer.Elapsed += (sender, args) =>
{
this.Cancel = true;
timer.Stop();
};
// Create
const string endpoint = "tcp://PC_ip:3245";
using (var request = new RequestSocket())
{
request.Bind(endpoint);
Thread.Sleep(2000);
while (!Cancel)
{
request.SendFrame("Requester says hello");
var reply = request.ReceiveFrameString();
Debug.WriteLine("Gets reply {0}",reply);
}
}
}
Reply socket code:
public void HelloWorld()
{
var timer = new Timer(60000);
const string endpoint = "tcp://PC_ip:3245";
timer.Start();
timer.Elapsed += (sender, args) =>
{
timer.Stop();
Cancel = true;
};
using (var replierSocket = new ResponseSocket())
{
replierSocket.Connect(endpoint);
Thread.Sleep(2000);
while (!Cancel)
{
var replyFromRequester = replierSocket.ReceiveFrameString();
Debug.WriteLine("Got reply {0}", replyFromRequester);
replierSocket.SendFrame("Response socket say hello");
}
}
}
Cancel is boolean
I went through some questions posted on this and added delay and these connection code blocks only trigger after button clicks on app.
While debugging , request.ReceiveFrameString() replierSocket.ReceiveFrameString(); are not even hit.
I am new to network programming , I understand that for REQ/REP pattern the code has to be in particular order which I traced and fixed I believe and turned off firewall on my PC so that firewall wont block my incoming connections from Android device.
PC_ip stands for IPv4 address I got from ipconfig /all for my wifi. I also tried external ip of my machine from sites like whatsmyip.org at ResponseSocket but I still dont get response between devices.
Please let me know what am I doing wrong.
Issue replication repository : GitHub/me/XamZeroMq

Related

How to make sockets work in xamarin?

In the Answer to this question Here:Server Client Application with .NET and Xamarin
the person who answered said: "On Xamarin.Android you can use all of the regular .Net socket classes"
I tried using the code in example of the Microsoft documentation and i had no errors but application just is just displaying like that on the phone:
If I delete the socket code it would display the page normally.My code behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using System.Net;
using System.Net.Sockets;
namespace App14
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class Page2 : ContentPage
{
public static string data = null;
public static void StartListening()
{
// Data buffer for incoming data.
byte[] bytes = new Byte[1024];
// Establish the local endpoint for the socket.
// Dns.GetHostName returns the name of the
// host running the application.
IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[0];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
// Create a TCP/IP socket.
Socket listener = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEndPoint);
listener.Listen(10);
// Start listening for connections.
while (true)
{
var label = new Label() { Text = "searching for a connection" };
// Program is suspended while waiting for an incoming connection.
Socket handler = listener.Accept();
label.Text = "Found a Connection";
data = null;
// An incoming connection needs to be processed.
while (true)
{
int bytesRec = handler.Receive(bytes);
data += Encoding.ASCII.GetString(bytes, 0, bytesRec);
if (data.IndexOf("<EOF>") > -1)
{
break;
}
}
// Show the data on the console.
label.Text = "Text received" + data;
// Echo the data back to the client.
byte[] msg = Encoding.ASCII.GetBytes(data);
handler.Send(msg);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public Page2 ()
{
StartListening();
Title = "Sign in page";
InitializeComponent();
}
private void page2_click(object sender,EventArgs e)
{
Navigation.PushAsync(new Page1(), true);
}
}
}
Xaml File code:
Why is this?.and can you please provide an example of client mobile or server mobile socket
You are blocking the UI Thread with your StartListening call, since it has a infinite while loop.
The label you create in the while loop is never added as content on the page. Hence the text you add to it will never be shown. You already have a label defined with the name l on the page. In this case you could just use that to add text:
l.Text = "hello";
As commented, you should start your socket listening code on another thread to not block you UI. This could be as simple as writing Task.Run(() => StartListening());. Make sure you understand what this does and possibly how you cancel this Task again when navigating away from the page or during App lifecycle.
If you try to Connect from your mobile with the correct ip address and port number of the Listener when both devices are in the same LAN it should work. If one of the devices is behind a different LAN router/modem you won't be able to connect because the router will block all incoming connections unless you use a port routing mechanism like UPnP.

How do I do TCP hole punching?

Question is below. Here is my current test code which did not succeed.
static void Main(string[] args)
{
if (args.Count() != 3)
{
Console.WriteLine("Bad args");
}
var ep = new IPEndPoint(IPAddress.Parse(args[0]), int.Parse(args[1]));
var lp = new IPEndPoint(IPAddress.Any, int.Parse(args[2]));
var s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
s.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
s.Bind(lp);
var c = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
c.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
c.Bind(lp);
Task.Run(() => { try { c.Connect(ep); } catch { } });
s.Listen(10);
var v = s.Accept();
v.Close();
}
How do I do TCP hole punching? I am testing using a remote server. I'm running wget local_public_ip:port/test. I have my router setup for port 80 so it doesn't need a hole punch. My code got a connection. Now I try on other ports and I can't exactly figure out how to punch the hole.
What I have done is (C# code)
var l = new TcpListener(8090);
l.Start();
try { var o = new TcpClient(); o.Connect("myserverip", 123); }
catch(Exception ex) {}
var e = l.AcceptSocket();
Console.WriteLine(e.RemoteEndPoint.AddressFamily);
I thought maybe I need to setup the local endpoint on the out tcp connection.
TcpClient(new System.Net.IPEndPoint(new System.Net.IPAddress(bytearray), port));
I made a mistake and got this exception
The requested address is not valid in its context
Fixing up the byte array to 192,168,1,5 it appears to make outgoing connects correctly. Now that I have a out connection to the remote IP using my listening port I thought wget would be able to connect to me. It wasn't the case
How do I do TCP hole punching?
I'd use the "sequential hole punching technique" detailed in http://www.bford.info/pub/net/p2pnat/index.html. It seems much simpler to do that simultaneous connections and socket reuse. It is not necessary for hole punching to do anything exactly simultaneously (that is a meaningless notion in distributed systems anyway).
I have implemented hole punching. My router seems not to like it. Wireshark shows the outbound hole punching SYN is correct but the remote party can't get through to me. I verifies all ports with TcpView.exe and disabled all firewalls. Must be a router issue. (It is a strange and invasive router.)
class HolePunchingTest
{
IPEndPoint localEndPoint;
IPEndPoint remoteEndPoint;
bool useParallelAlgorithm;
public static void Run()
{
var ipHostEntry = Dns.GetHostEntry("REMOTE_HOST");
new HolePunchingTest()
{
localEndPoint = new IPEndPoint(IPAddress.Parse("LOCAL_IP"), 1234),
remoteEndPoint = new IPEndPoint(ipHostEntry.AddressList.First().Address, 1235),
useParallelAlgorithm = true,
}.RunImpl();
}
void RunImpl()
{
if (useParallelAlgorithm)
{
Parallel.Invoke(() =>
{
while (true)
{
PunchHole();
}
},
() => RunServer());
}
else
{
PunchHole();
RunServer();
}
}
void PunchHole()
{
Console.WriteLine("Punching hole...");
using (var punchSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
EnableReuseAddress(punchSocket);
punchSocket.Bind(localEndPoint);
try
{
punchSocket.Connect(remoteEndPoint);
Debug.Assert(false);
}
catch (SocketException socketException)
{
Console.WriteLine("Punching hole: " + socketException.SocketErrorCode);
Debug.Assert(socketException.SocketErrorCode == SocketError.TimedOut || socketException.SocketErrorCode == SocketError.ConnectionRefused);
}
}
Console.WriteLine("Hole punch completed.");
}
void RunServer()
{
using (var listeningSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
EnableReuseAddress(listeningSocket);
listeningSocket.Bind(localEndPoint);
listeningSocket.Listen(0);
while (true)
{
var connectionSocket = listeningSocket.Accept();
Task.Run(() => ProcessConnection(connectionSocket));
}
}
}
void ProcessConnection(Socket connectionSocket)
{
Console.WriteLine("Socket accepted.");
using (connectionSocket)
{
connectionSocket.Shutdown(SocketShutdown.Both);
}
Console.WriteLine("Socket shut down.");
}
void EnableReuseAddress(Socket socket)
{
if (useParallelAlgorithm)
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
}
}
You can try both values for useParallelAlgorithm. Both should work.
This code is for the server. It punches a hole into the local NAT. You can then connect from the remote side using any client that allows to pick the local port. I used curl.exe. Apparently, telnet on Windows does not support binding to a port. wget apparently neither.
Verify that the ports are correct on both sides using TcpView or Process Explorer. You can use Wireshark to verify packets. Set a filter like tcp.port = 1234.
When you "call out" to punch a hole you enable the tuple (your-ip, your-port, remote-ip, remote-port) to communicate. This means that all further communication must use those values. All sockets (inbound or outbound) must use these exact port numbers. In case you aren't aware: outgoing connections can control the local port as well. This is just uncommon.

Cloud Service for incoming TCP connections hangs

I'm developing a cloud service (worker role) for collecting data from a number of instruments. These instruments reports data randomly every minute or so. The service itself is not performance critical and doesn't need to be asynchronous. The instruments are able to resend their data up to an hour on failed connection attempt.
I have tried several implementations for my cloud service including this one:
http://msdn.microsoft.com/en-us/library/system.net.sockets.tcplistener.stop(v=vs.110).aspx
But all of them hang my cloud server sooner or later (sometimes within an hour).
I suspect something is wrong with my code. I have a lot of logging in my code but I get no errors. The service just stops to receive incoming connections.
In Azure portal it seems like the service is running fine. No error logs and no suspicious cpu usage etc.
If I restart the service it will run fine again until it hangs next time.
Would be most grateful if someone could help me with this.
public class WorkerRole : RoleEntryPoint
{
private LoggingService _loggingService;
public override void Run()
{
_loggingService = new LoggingService();
StartListeningForIncommingTCPConnections();
}
private void StartListeningForIncommingTCPConnections()
{
TcpListener listener = null;
try
{
listener = new TcpListener(RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["WatchMeEndpoint"].IPEndpoint);
listener.Start();
while (true)
{
_loggingService.Log(SeverityLevel.Info, "Waiting for connection...");
var client = listener.AcceptTcpClient();
var remoteEndPoint = client.Client != null ? client.Client.RemoteEndPoint.ToString() : "Unknown";
_loggingService.Log(SeverityLevel.Info, String.Format("Connected to {0}", remoteEndPoint));
var netStream = client.GetStream();
var data = String.Empty;
using (var reader = new StreamReader(netStream, Encoding.ASCII))
{
data = reader.ReadToEnd();
}
_loggingService.Log(SeverityLevel.Info, "Received data: " + data);
ProcessData(data); //data is processed and stored in database (all resources are released when done)
client.Close();
_loggingService.Log(SeverityLevel.Info, String.Format("Connection closed for {0}", remoteEndPoint));
}
}
catch (Exception exception)
{
_loggingService.Log(SeverityLevel.Error, exception.Message);
}
finally
{
if (listener != null)
listener.Stop();
}
}
private void ProcessData(String data)
{
try
{
var processor = new Processor();
var lines = data.Split('\n');
foreach (var line in lines)
processor.ProcessLine(line);
processor.ProcessMessage();
}
catch (Exception ex)
{
_loggingService.Log(SeverityLevel.Error, ex.Message);
throw new Exception(ex.InnerException.Message);
}
}
}
One strange observation i just did:
I checked the log recently and no instrument has connected for the last 30 minutes (which indicates that the service is down).
I connected to the service myself via a TCP client i've written myself and uploaded some test data.
This worked fine.
When I checked the log again my test data had been stored.
The strange thing is, that 4 other instruments had connected about the same time and send their data successfully.
Why couldn't they connect by themself before I connected with my test client?
Also, what does this setting in .csdef do for an InputEndpoint, idleTimeoutInMinutes?
===============================================
Edit:
Since a cuple of days back my cloud service has been running successfully.
Unfortunately this morning last log entry was from this line:
_loggingService.Log(SeverityLevel.Info, String.Format("Connected to {0}", remoteEndPoint));
No other connections could be made after this. Not even from my own test TCP client (didn't get any error though, but no data was stored and no new logs).
This makes me think that following code causes the service to hang:
var netStream = client.GetStream();
var data = String.Empty;
using (var reader = new StreamReader(netStream, Encoding.ASCII))
{
data = reader.ReadToEnd();
}
I've read somewhere that StremReader's ReadToEnd() could hang. Is this possible?
I have now changed this piece of code to this:
int i;
var bytes = new Byte[256];
var data = new StringBuilder();
const int dataLimit = 10;
var dataCount = 0;
while ((i = netStream.Read(bytes, 0, bytes.Length)) != 0)
{
data.Append(Encoding.ASCII.GetString(bytes, 0, i));
if (dataCount >= dataLimit)
{
_loggingService.Log(SeverityLevel.Error, "Reached data limit");
break;
}
dataCount++;
}
Another explanation could be something hanging in the database. I use the SqlConnection and SqlCommand classes to read and write to my database. I always close my connection afterwards (finally block).
SqlConnection and SqlCommand should have default timeouts, right?
===============================================
Edit:
After some more debugging I found out that when the service wasn't responding it "hanged" on this line of code:
while ((i = netStream.Read(bytes, 0, bytes.Length)) != 0)
After some digging I found out that the NetStream class and its read methods could actually hang. Even though MS declares otherwise.
NetworkStream read hangs
I've now changed my code into this:
Thread thread = null;
var task = Task.Factory.StartNew(() =>
{
thread = Thread.CurrentThread;
while ((i = netStream.Read(bytes, 0, bytes.Length)) != 0)
{
// Translate data bytes to a ASCII string.
data.Append(Encoding.ASCII.GetString(bytes, 0, i));
}
streamReadSucceeded = true;
});
task.Wait(5000);
if (streamReadSucceeded)
{
//Process data
}
else
{
thread.Abort();
}
Hopefully this will stop the hanging.
I'd say that part of your problem is you are processing your data on the thread that listens for connections from clients. This would prevent new clients from connecting if another client has started a long running operation of some type. I'd suggest you defer your processing to worker threads thus freeing the "listener" thread to accept new connections.
Another problem you could be experiencing, if your service throws an error, then the service will stop accepting connections as well.
private static void ListenForClients()
{
tcpListener.Start();
while (true)
{
TcpClient client = tcpListener.AcceptTcpClient();
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
}
private static void HandleClientComm(object obj)
{
try
{
using(TcpClient tcpClient = (TcpClient)obj)
{
Console.WriteLine("Got Client...");
using (NetworkStream clientStream = tcpClient.GetStream())
using (StreamWriter writer = new StreamWriter(clientStream))
using(StreamReader reader = new StreamReader(clientStream))
{
//do stuff
}
}
}
catch(Exception ex)
{
}
}

Why doesn't the NetworkUp event fire on the .Net Gadgeteer GHI WiFi RS21 module?

I'm trying to debug why the event NetworkUp never fires on the WiFi RS21 Gadgeteer module and I've distilled it down to a very simple code listing:
using Microsoft.SPOT;
using Gadgeteer.Networking;
using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;
namespace NetworkUpTest
{
public partial class Program
{
void ProgramStarted()
{
wifi_RS21.UseDHCP();
wifi_RS21.NetworkUp += wifi_RS21_NetworkUp;
wifi_RS21.NetworkDown += wifi_RS21_NetworkDown;
var scans = wifi_RS21.Interface.Scan("LLOYDREGANS");
if (scans != null && scans.Length > 0)
{
Debug.Print("Joining " + scans[0].SSID);
wifi_RS21.Interface.Join(scans[0], "**********");
}
var giveUpWaitingForTheNetworkUpEvent = new GT.Timer(300000, GT.Timer.BehaviorType.RunOnce);
giveUpWaitingForTheNetworkUpEvent.Tick += giveUpWaitingForTheNetworkUpEvent_Tick;
giveUpWaitingForTheNetworkUpEvent.Start();
}
void wifi_RS21_NetworkUp(GTM.Module.NetworkModule sender, GTM.Module.NetworkModule.NetworkState state)
{
Debug.Print("NetworkUp");
}
void wifi_RS21_NetworkDown(GTM.Module.NetworkModule sender, GTM.Module.NetworkModule.NetworkState state)
{
Debug.Print("NetworkDown");
}
void giveUpWaitingForTheNetworkUpEvent_Tick(GT.Timer timer)
{
Debug.Print("Give up waiting for the NetworkUp event and try requesting the router homepage");
var request = HttpHelper.CreateHttpGetRequest("http://192.168.1.1/");
request.ResponseReceived += request_ResponseReceived;
request.SendRequest();
}
void request_ResponseReceived(HttpRequest sender, HttpResponse response)
{
Debug.Print("Response received. response.Text.Length = " + response.Text.Length);
}
}
}
Here's the listing from the output window when the program runs (minus the thread exited reports):
Using mainboard GHI Electronics FEZSpider version 1.0
RS9110 firmware version Number is 4.4.5
RS9110 driver version Number is 4.4.5
Joining LLOYDREGANS
NetworkDown
Give up waiting for the NetworkUp event and try requesting the router homepage
Response received. response.Text.Length = 2509
Given that the network is demonstrably up, why is "NetworkDown" the only event that fires from the WiFi RS21 module?
The answer on the GHI forum suggests that the correct events to use are:
Interface.WirelessConnectivityChanged
Interface.NetworkAddressChanged
instead of the exemplar code on GHI's WiFi RS21 Gadgeteer module page.

ConnectAsync blocking UI Thread

I have simple WinRT application, that will be communicating with remote server via TCP.
In order to do that I'm creating new StreamSocket object, and connecting to remote server after clicking a proper button, like this:
private async void ConnectButtonClick(object sender, RoutedEventArgs e)
{
StreamSocket socket = new StreamSocket();
HostName host = new HostName("192.168.1.15");
await socket.ConnectAsync(host, "12121");
}
The problem is that this code is blocking the UI thread. I've created simple animation, using MonoGame (couple of moving sprites) that is running on the screen continously, in order to check if UI is blocked.
The problem is, that after clicking Connect button, animation is freezing for a second, so I assume that, connecting to the server is made in the UI thread.
Should I put my whole network code into a separate thread, or is this async/await enough?
I'd like to implement a loop, that will handle incoming data (with help od DataReader), like this:
private async void ReceiveLoop()
{
bool running = true;
while (running)
{
try
{
uint numStrBytes = await _reader.LoadAsync(BufferSize);
if (numStrBytes == 0)
{
Disconnect();
return;
}
string msg = _reader.ReadString(numStrBytes);
OnLog(string.Format("Received: {0}", msg));
OnDataReceived(msg);
}
catch (Exception exception)
{
OnLog("Receive failed with error: " + exception.Message);
Disconnect();
running = false;
}
}
}
Sending data will be done using StoreAsync from DataWriter.
So should I put these functions into separate threads?
Can't you just try doing that on a background thread to see if that helps? Something like this:
Task.Run(
async () =>
{
StreamSocket socket = new StreamSocket();
HostName host = new HostName("192.168.1.15");
await socket.ConnectAsync(host, "12121");
});
For any async calls in a normal .net library, the general rule is to use ConfigureAwait(false) which helps prevent issues like you are seeing. So for instance in WinRT stuff it would be:
await socket.ConnectAsync(host, "12121").AsTask().ConfigureAwait(false);
This has some great information:
http://blogs.msdn.com/b/windowsappdev/archive/2012/04/24/diving-deep-with-winrt-and-await.aspx