Discovery in c# - c#

I've to implement some discovery for an internal solution.
We have two kind of software:
Server: They manage a lot of hardware devices and can give access to some data (.Net remoting)
Client: They can display data of one or several Server(graphs, stats, ...)
Currently we are setting the IP by hand on the client.
We would like to implement a discovery.
We have the following requirement:
It has to be usable in c#
When a server is up, it must be displayed as available very fastly
Same when it shut down
If the server doesn't stops in a clean way, we can have a way to detect it(no need to be very fast, can be done every 10-15min).
It can give me some information(Server version, port to use, ...)
We have client computer with multiple network cards, we must discover server on each cards
Do you have a protocol, a library, ... to advice?
We tried UPnP, but seems there is no good Server+client implementation in c# that meet our requirement

Use UDP broadcasts from the discovering app (client):
int broadcastPort = //something
byte[] msg = //something
//Cycle this for all IP adresses
IPAddress broadcastIp = //Broadcast address for this net
IPEndPoint destinationEndpoint = new IPEndPoint(broadcastIp, broadcastPort);
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
sock.SendTo(msg, broadcastEndpoint);
And have the discovered app (Server) answer, to receive the answer use UdpClient.Receive(), which gives you the IP of the answering station.

Related

Server Client Application with .NET and Xamarin

I searched around the internet a lot of hours but I couldn't find anything that matches my case.
I simply want to implement a Server/Client App with TCP or UDP where my Android App (Xamarin) acts as a server and my .NET application as Client. Since I have not much experience with app development and no experience with Xamarin, I was looking for an example. All I found was this:
http://www.codeproject.com/Articles/340714/Android-How-to-communicate-with-NET-application-vi
First of all this is the opposite way (Server on .NET and Client as App) and additionaly it is for Android Studio so it's hard for me to translate these things into Xamarin without errors.
Please can someone help and give me an example how to realize my issue?
Thank you!
On Xamarin.Android you can use all of the regular .Net socket classes:
Namespaces:
using System.Net;
using System.Net.Sockets;
Example:
IPHostEntry ipHostInfo = Dns.GetHostEntry (Dns.GetHostName ());
IPAddress ipAddress = ipHostInfo.AddressList [0];
IPEndPoint localEndPoint = new IPEndPoint (ipAddress, 11000);
System.Diagnostics.Debug.WriteLine(ipAddress.ToString());
// Create a TCP/IP socket.
Socket listener = new Socket (AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
AndroidManifest.xml Required Permissions are:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
The MSDN-based Asynchronous Server Socket example works as a cut/paste example with no changes.
i.e.
Using the MSDN code, you can call the static method, AsynchronousSocketListener.StartListening, in a thread to start listening on port 11000 defined in the AsynchronousSocketListener class.
new Thread (new ThreadStart (delegate {
AsynchronousSocketListener.StartListening();
})).Start ();
Once it is running on your device/emulator, you can telnet into your Android TCP socket server:
>telnet 10.71.34.100 11000
Trying 10.71.34.100...
Connected to 10.71.34.100.
Escape character is '^]'.
Once connected, type in This is a test<EOF> and the Android will echo it back:
This is a test<EOF>
You do this like in normal .net, except you have to ask permissions to use sockets.
There are tons of simple example of creating a listening tcp connection in c#.
The problem you will have is to know the IP address of your server (in the phone) as it will likely change often when the user is moving.

Allow client app to automatically connect to server app on same network

I've created two apps (A client and a server) which can communicate with each other as long as I input the local IP address of the machine the server app is running on into the client app (in code).
I would like the client app to automatically discover the local IP address of the machine running the server app and connect to it, so they can be run on any network without the need to enter the IP in code.
Both of these apps with be running on the same network (ie. Over WiFi, not the Internet)
Here is what I have so far in my client app:
// COMMUNICATE WITH SERVER
private TcpClient client = new TcpClient();
private IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("192.168.2.35"), 8888);
public Console()
{
InitializeComponent();
client.Connect(serverEndPoint);
}
private void SendMessage(string msg)
{
NetworkStream clientStream = client.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(msg);
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
}
In this example I can only connect to a server running on "192.168.2.35", I would like it to be able to find the server running on port 8888 on any machine on the network.
Alternatively, if this isn't possible I would like the server to broadcast its IP as a message (of some sort) and have the client receive this message and verify it is the server and connect to it.
I think my second example is the proper way to do this, but I can't seem to wrap my head around how to get it working (I'm fairly new to C#), and any other examples I've found I can't seem to get to work with my applications.
Here is my server code if it helps answer my question:
private void Server()
{
this.tcpListener = new TcpListener(IPAddress.Any, 8888);
this.listenThread = new Thread(new ThreadStart(ListenForClients));
this.listenThread.Start();
}
private void ListenForClients()
{
this.tcpListener.Start();
while (true)
{
TcpClient client = this.tcpListener.AcceptTcpClient();
connectedClients++;
lblNumberOfConnections.Text = connectedClients.ToString();
Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
clientThread.Start(client);
}
Thanks
EDIT: I've tried adding THIS to my project, but being so new I'm unsure how to implement it properly, and it didn't get me anywhere.
2nd EDIT: I've tried implementing a UDP broadcast a few times now, with no luck on any attempt yet. My latest attempt was at implementing THIS (minus the chat parts). I just can't seem to get a UDP broadcast working at all with my project, as it seems to be way over my head at my current skill level. Unfortunately, having my client automatically connect to the server is 100% necessary for my project to function...
My other problem, which is maybe best to start a separate question for, but somewhat correlates to this issue is: My client GUI consists of a panel that switches between multiple custom classes, each containing different buttons, etc. (works similar to tab pages) that communicate to the server I'm trying to connect to. Once I get the UDP broadcast figured out, will I need to code that into every class separately? or is there a way of having all classes running in my panel connect to the same server?
A simple, but possibly costly(in terms of network traffic) solution would be for your server application to broadcast over UDP it's application and connection info. Your client could listen for all broadcast packets that have your servers custom header. Assuming a connection is made you could stop the broadcast. The downside is you would have to be broadcasting constantly if a client is not connected and this can clog your network if there aren't limits placed on the broadcast speed.
EDIT: Here is a boiled down explanation generated from the MSDN article https://msdn.microsoft.com/en-us/library/tst0kwb1(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1
EDIT #2: I've expanded on this answer on my blog, as well as provided downloadable example projects. the article can be found at http://martialdeveloper.com/wordpress/?p=21
1. Find your network's broadcast IP
A special “Broadcast Address” must be used when using UDP for the purpose of sending a datagram to all machines connected to a given network. For example, the typical home network host/gateway of 192.168.0.1 has a broadcast address of 192.168.0.255. If your network differs from this you can use an IPv4 broadcast address calculator like the one found here http://jodies.de/ipcalc
Or read the introductory section on MSDN describing the broadcast address. https://msdn.microsoft.com/en-us/library/tst0kwb1(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1
2. Select a listening/broadcast port
Any port that is free on your client & server is fine. The MSDN example uses 11000. This port number is used in your broadcaster, and listener.
3. Code for the Listener
Note to the reader. All error handling has been omitted for clarity of the example.
int listenPort = 11000;
bool done = false;
UdpClient listener = new UdpClient(listenPort);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any,listenPort);
while (!done) // This loop listens for your broadcast packets
{
Console.WriteLine("Waiting for broadcast");
byte[] bytes = listener.Receive( ref groupEP);
Console.WriteLine("Received broadcast from {0} :\n {1}\n",
groupEP.ToString(),
Encoding.ASCII.GetString(bytes,0,bytes.Length));
}
listener.Close();
Note: The third parameter to Console.WriteLine, "Encoding.ASCII..." represents the string value sent over UDP in the datagram packet. This contains the desired negotiation information for a discovery situation, such as the IP address of the client or server you wish to connect to.
4. Code for the Broadcaster
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp);
IPAddress broadcast = IPAddress.Parse("This string should be the broadcast IP address"); //NOTE: Broadcast IP goes here!!
byte[] sendbuf = Encoding.ASCII.GetBytes("This is the message string to be broadcast"); //Your message to the client/server goes here, I.E. an
// app/client name or ID and an IP to connect with over TCP
IPEndPoint ep = new IPEndPoint(broadcast, 11000);
s.SendTo(sendbuf, ep);
Console.WriteLine("Message sent to the broadcast address");
NOTE: This is a very simple example. The broadcaster may need to rebroadcast for a period of time to make sure the Listener receives it. Even after the UDP datagram is sent/received there will need to be some negotiation to ensure the TCP connection is made properly.

A service that makes tcp connections to multiple clients

Most of the examples online are examples of a multithreaded tcp server, whereby the server listens for multiple incoming connections from the client.
What I'm looking for is for the "server", to initiate the connections. If I have 100 devices (all different IP address of course), my server will have to make 100 individual connections to each device and receive data from the devices.
This is how I would make my connection to a device
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
_socket.SendTimeout = 2000;
_socket.ReceiveTimeout = 2000;
_socket.Connect(new IPEndPoint(IPAddress, TCPPort));
But I would like to know if there's any component out there, that would fulfill the following
establish as many tcp connections as I want to the devices
receive & send data through the connection
handle tcp timeouts/disconnects/etc & re-establish connection to the IP
If there aren't any of such components, are there any tips as to how I should go about doing it? e.g., 1 connection per thread, or how do I handle if the data is received in multiple packets, etc?
Any insights would be greatly appreciated
There are several existing components out there that you could use to achieve what you want. Checkout http://www.networkcomms.net and http://code.google.com/p/lidgren-network-gen3/.
Having said that people always prefer to add that there is nothing stopping you writing everything from scratch yourself as per the example you give.
Disclaimer: I'm a developer for NetworkComms.Net.

C# Unable to receive WOL package with UdpClient

I'm trying to receive a WOL package within my C# application. I guess the problem why it doesn't work has something to do with how the package is broadcasted by my router running DD-WRT.
The code I use to receive an UDP package:
UdpClient udp = new UdpClient(10);
IPEndPoint all = new IPEndPoint(IPAddress.Any, 0);
while (true)
{
System.Diagnostics.Debug.Print("listening");
byte[] receivedBytes = udp.Receive(ref all);
System.Diagnostics.Debug.Print(Encoding.ASCII.GetString(receivedBytes));
}
This already worked with my old router but now I have DD-WRT running and it had to be setup like this:
I port-forward incoming UDP packages on Port 10 to the (non existing) IP 192.168.1.254
On startup of the router the command "arp -i br0 -s 192.168.1.254 FF:FF:FF:FF:FF:FF" is executed to broadcast the messages received on that IP.
This setup works, a magic package is received by every machine and I can wake them up from outside of my network.
WireShark is able to catch this packages but "udp.Receive(ref all);" is not. This is how a WOL package send to my router looks like in Wireshark:
http://i.stack.imgur.com/nxaAP.png
If I send (from within my C# application) a Broadcasted UDP MagicPackage on the other hand, this package is received by my code above. This MagicPackage shows up in Wireshark like this:
http://i.stack.imgur.com/tPU1v.png
So I'm not 100% sure if the different "Destination" (192.168.1.254 versus 255.255.255.255) or the different "Protocoll" (WOL versus UDP) is the problem. My guess is, that the UdpClient ignores the WOL package because it's destination (within the IP header) is a different IP address (the code is running on machine 192.168.1.2). The second package on the other hand has a destination address of "255.255.255.255" in its IP Header and is therefor catched by the UdpClient.
So the big question is: How do I set up an UDP listener that also receives the WOL package broadcasted by my router?
BTW: I also already tried it with this code but without any luck:
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
EndPoint iep = new IPEndPoint(IPAddress.Any, 10);
sock.Bind(iep);
byte[] data = new byte[1024];
int recv = sock.ReceiveFrom(data, ref iep);
Check this property:
http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.enablebroadcast.aspx
I believe WOL packets are broadcasted. In this case it should help.
EDIT:
After checking your Wireshark screenshot I think the issue is not in your code. As far as I know there are many filters in network stack. The first one is MAC filter. WOL packet will go throught because of broadcast address ff:ff:ff.... The second filter is on IP Address. Your WOL packet has destination IP ...1.254, but your OS is expecting ...1.2 and therefor the IP stack will throw this packet and your app will not receive anything. Wireshark on the other side switches the network card to "promiscuous mode" where all filters are turned off and wireshark is able to capture everything.
So to solve this:
1) You can implement similar behavior as Wireshark using some capture library - take a look at WinPCAP - http://www.winpcap.org/
2) Try to use RAW sockets, but I am not sure that this will work - http://en.wikipedia.org/wiki/Raw_socket
3) Best way would be to fix your router to send WOLs in standard format.

UDP Hole Punching help

I'm trying to add networking over the internet to my game, using Peer to Peer.
I have already implemented a LAN only version, which uses .NET's peer to peer classes to connect within the local network.
I realized I need to use UDP hole punching in order to establish a connection to other clients that are behind a firewall.
This is how I have started to implement it:
The server is a HTTP server using very simple PHP scripts to get the job done.
register name on server, sending the private ip address and port as a GET variable
when the server gets a registration request, it will save the public endpoint and the private endpoint
request to connect to another client.
the server will return the private and public endpoints of the client
every two seconds, the second client will check in with the server, and if there is another client attempting to connect with it, it will get its endpoints too
both clients start spamming each others public endpoints until they get a valid response
Now I have a bunch of questions
Can the server be a HTTP server?
When I make a request to an HTTP server, the client port changes each time a request is made. Is a private endpoint always matched to the same public endpoint?
Does the request to the server have to have the same source endpoint as the UDP messages to the client?
Is there a way to connect to an HTTP server in C# using a specified source endpoint?
Are there any problems with my implementation?
Thanks!
UDP hole punching is a complex topic, and many attempts have been made to find a solution that works. The problem is that there are so many different NAT routers out there, and there is no standard way of implementing NAT, so all routers behave a bit different.
Some attempts have been standardized, e.g. STUN, ICE. They still work only in most cases, not all, but they accumulate a lot of knowledge and address many concerns -- more than your attempt will ever be able to, simply because you can't test your solution with every NAT router under the sun. Skype, for example, spent years of perfecting its NAT traversal mechanism.
I recommend you have a look at STUN or preferably ICE. Try to implement one of them or look for existing implementations.
Another option might be to simply create a port forward at the router, e.g. using UPnP or NAT-PMP.
That said, I wouldn't be surprised if the .NET peer to peer classes came with a NAT traversal mechanism, but I'm not familiar with them.
STUN is a best solution for the problem. it works for most of the scenarios.here is a simple example(C#) that gives you the NAT type,Local IP:Port and Public IP:Port.
try
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socket.Bind(new IPEndPoint(IPAddress.Any, 0));
STUN_Result result = STUN_Client.Query("stunserver.org", 3478, socket);
Console.WriteLine("Net Type : " + result.NetType.ToString());
Console.WriteLine("Local IP : " + socket.LocalEndPoint.ToString());
if (result.NetType != STUN_NetType.UdpBlocked)
{
Console.WriteLine("Public IP : " + result.PublicEndPoint.ToString());
}
else
{
Console.WriteLine("");
}
}
catch (Exception x)
{
Console.WriteLine(x.StackTrace.ToString());
}
You can just add some breakpoints and check the behaviour of the code.
also you can traverse NAT using vs2010 onwords (.net4.0 < ) . there is a method AllowNATTraversal (bool value). set the value true for NAT Traverse. It uses Ipv6 address for connectivity. You can get Ipv6 global address from "Teredo" server by writing some commands in command prompt. Actually IPV6 is the technology that is used to avoid this problem.

Categories