c# : UDPClient not receiving multicast from one of the Network Adapters - c#

I would like to test Receive of multicast messages using UDP Client
I have two network adapters.
Network 1: with local IP : 10.239.1.1 [Multicast Group : 224.1.1.1 : 42333]
Network 2 : with local IP : 172.4.1.1 [Multicast Group : 224.0.1.1 : 42333]
Note : I can see all the multicast on wire shark
In my program I created and joined the multicast group as bellow.
_LocalUDPClient = new UdpClient(new IPEndPoint(_localIpAddress, _multiCastPort));
_LocalUDPClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_LocalUDPClient.JoinMulticastGroup(_multicastIpAddress, _localIpAddress);
_LocalUDPClient.BeginReceive(new AsyncCallback(ReceiveCallBack), null);
Network 1 :
_localIpAddress = 10.239.1.1
_multicastIpAddress = 224.1.1.1
_multiCastPort = 42333
I receive multicast message successfully.
BUT
Network 2 :
_localIpAddress = 172.4.1.1
_multicastIpAddress = 224.0.1.1
_multiCastPort = 42333
Not receiving any Multicast data.

It is not a c# code issue, It is Firewall issue.
open firewall and network protection under system settings
You should be able to see your .exe under "Allow an app through firewall".
In my case I can see it 3 times with different settings.
I deleted all and added manually my program .exe with allow for all network types, I got multicasts now.

Related

Simple Webrtc relay bridge Server in C#

I have a fully working peerTopeer (P1, P2) webRTC. To handle peerTopeer failures, I am trying for a simple exchange of bytes via a server in c# between P1 and P2 on a windows machine, as I don't want to develop a turn server by specs. I have also tried to find an open source c# server turn server with turn message but its not working (able to parse request but response seems to be not accepted by latest chrome/MS Edge chromium based)
Simple C# relay bridge server:
With simple udp/tcp listener and exchange of bytes with peers, (P1 to P2 and P2 to P1) and forcing bridge machine IP as candidate I am able to achieve connections and streaming data (bytes) are exchanged.
However unable to see video/hear audio on peers and also after some exchange, the connections are dropped with connectionState failed on the client side.
Q1. It should have worked, what is going wrong?
Q2. Any opensource c# implementation of stun and turn (simple one)?
I appreciate any help in this regard.
Server and Client code samples:
Listen to tcp / udp(not in sample)
public void ListenTCP(int port) {
TcpListener listener = new TcpListener(IPAddress.Any, port);
listener.Start();
while (true){
TcpClient tcpClient = listener.AcceptTcpClient();
..........add endpoint to list
var bytes = readfromtcpstream.......;
Task.Run(() => ProcessData(tcpClient.Client.RemoteEndPoint, bytes));
}
}
ProcessData (exchange stream bytes)
private void Process_DATA(IPEndPoint fromEndPoint, byte[] bytes) {
foreach (var endpoint in list) { //distribute to all other peers
if (endpoint == fromEndPoint) continue;
endpoint's TCPClient.Send(bytes);
}
}
On the client side (Javascript / typescript), forcing the candidate as bridge server
SignalType.Candidate...
candidate = new RTCIceCandidate(Switch the SDP(messageJson.candidate,
BridgeServerAddress, "2525", "tcp"));
m_PeerConnection.addIceCandidate(candidate)
Simply modifying the ice candidate you got from P2P is unlikely to work since TCP candidates work a bit differently. And a TURN server is very different from a simple bridge.
The following SDP contains a TCP candidate with tcptype passive which will make the other side establish a connection to it. Feed it into setRemoteDescription, then create an answer and call setLocalDescription with the answer.
v=0
o=- 2576067654554894849 3 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE audio
a=msid-semantic: WMS
m=audio 9 UDP/TLS/RTP/SAVPF 111
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=candidate:2698387310 1 tcp 25042943 127.0.0.1 31337 typ host tcptype passive generation 0
a=ice-ufrag:server
a=ice-pwd:Kv6yCw1HiZ1/6uNExYcE28pO
a=fingerprint:sha-256 22:46:36:8D:B1:CD:08:7B:A1:60:86:BF:95:90:06:4B:EA:47:D9:74:24:FF:6D:2F:1C:09:5B:C1:F5:8D:CC:B2
a=setup:actpass
a=mid:audio
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=recvonly
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
The browser should establish a connection to port 31337 on localhost (note that Firefox doesn't allow localhost ICE by default so try this in Chrome first).
From there, you'll have to process ICE, decrypt SRTP etc.

how to use my public IP with HttpListener

I've got this so far...
public static HttpListener listener = new HttpListener();
public static string startUpPath = Application.StartupPath;
public WebServer()
{
listener.Start();
listener.Prefixes.Add("http://(here I want my public ip)/");
Thread t = new Thread(new ThreadStart(clientListener));
t.Start();
}
But when I initialize the class it says "The specified Network format is not valid"
The translation may not be perfect because my visual studio language is in Spanish.
My ip looks like 95.^^.^^^.^^ and I think that may be the problem because it works when I use my local ip.
//Edited
The exact exception is:
"El formato del nombre de red especificado no es vĂ¡lido"
Which is"The specified network name is not valid".
If I add the prefix
"http:// + :80/"
it still going, but how can I access that through my public ip?
When setting this up you should use your internal IP, since that is the actual IP you are listening on.
In-order to get traffic from the your external IP, you need to forward that traffic from your router to your computer that is listening on its internal IP.
One way to set it up is to use port forwarding, from your router, you would want to direct any traffic that comes in on port 80 to your computer.
More info:
http://en.wikipedia.org/wiki/Port_forwarding
As Jamie said, your HTTPListener should be bound to the IP address on the network card where the application is running. Unless you have a NIC that is actually configured with a public IP (e.g. not going through a router) then your private address is the one to use.
An easy way to check this is to run IPCONFIG and see what IP address is listed.

Can't bind DatagramSocket on "0.0.0.0"

in Win RT we have to use DatagramSocket instead of UdpClient. Ok but the following code gives me this error which I don't get on UdpClient.
var g = new DatagramSocket();
g.MessageReceived += g_MessageReceived;
await g.BindEndpointAsync(new HostName("0.0.0.0"), "5000"); //<--- this line
*IPAddress.Any = 0.0.0.0
I get this Error:
"No such host is known. (Exception from HRESULT: 0x80072AF9)"
To bind to all local interfaces (the way binding 0.0.0.0 aka INADDR_ANY does with the Berkeley Sockets API), use BindServiceNameAsync.
The BindServiceNameAsync method binds to the local IP addresses of all network interfaces on the local computer on the local service name or UDP port specified in the localServiceName parameter. If the localServiceName parameter is an empty string, the system will select the local UDP port on which to bind.

How do I determine local IP address which can connect to a given remote IP/DNS Address

Using C# Winforms I am trying to automatically detect the local machines IP address through which it can connect to a particular remote DNS/IP address.
One senario is running over a VPN, with the remote address being 10.8.0.1 and local address being 10.8.0.6, netmask of 255.255.255.252
Iterating through the local addresses and checking if the remote and local are on the same subnet obviously fails and I am unsure of how else to do this.
Here is some sample code that should get you the information you're looking for. It creates a UDP socket and calls Connect() on it (effectively a NOOP), and then checks the local address.
static EndPoint GetLocalEndPointFor(IPAddress remote)
{
using (Socket s = new Socket(remote.AddressFamily,
SocketType.Dgram,
ProtocolType.IP))
{
// Just picked a random port, you could make this application
// specific if you want, but I don't think it really matters
s.Connect(new IPEndPoint(remote, 35353));
return s.LocalEndPoint;
}
}
static void Main(string[] args)
{
IPAddress remoteAddress = IPAddress.Parse("10.8.0.1");
IPEndPoint localEndPoint = GetLocalEndPointFor(remoteAddress) as IPEndPoint;
if (localEndPoint == null)
Console.WriteLine("Couldn't find local address");
else
Console.WriteLine(localEndPoint.Address);
Console.ReadKey();
}
Note that this is effectively an implementation of this answer, but in C#.
The routing table determines which local port to use. I don't know of a way from C# to get it other than to run the route print CLI command. If there is a network match it uses that port, otherwise it uses the default route.
http://www.csharp-examples.net/local-ip/
Give that a shot.

What is the best way for a client app to find a server on a local network in C#?

The client connects to the server using GenuineChannels (we are considering switching to DotNetRemoting). What I mean by find is obtain the IP and port number of a server to connect to.
It seems like a brute-force approach would be try every IP on the network try the active ports (not even sure if that's possible) but there must be a better way.
Consider broadcasting a specific UDP packet. When the server or servers see the broadcasted UDP packet they send a reply. The client can collect the replies from all the servers and start connecting to them or based on an election algorithm.
See example for client (untested code):
using System.Net;
using System.Net.Sockets;
[STAThread]
static void Main(string[] args)
{
Socket socket = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
socket.Bind(new IPEndPoint(IPAddress.Any, 8002));
socket.Connect(new IPEndPoint(IPAddress.Broadcast, 8001));
socket.Send(System.Text.ASCIIEncoding.ASCII.GetBytes("hello"));
int availableBytes = socket.Available;
if (availableBytes > 0)
{
byte[] buffer = new byte[availableBytes];
socket.Receive(buffer, 0, availableBytes, SocketFlags.None);
// buffer has the information on how to connect to the server
}
}
I'd say the best way is to use Bonjour/Zeroconf/mDNS for C#; a lot of thought went into making it play nice with the network; IE it pings less frequently over time if possible, etc. There's Mono.Zeroconf, and I read there's an older .NET project in the Apple SDK but I haven't found it.
So the easiest would be to install Bonjour for Windows, then get the Windows Binaries for Mono.Zeroconf try the example MZClient.exe drop the Mono.Zeroconf.dll and/or Mono.Zeroconf.Providers.Bonjour.dll into your project references and go.
Something like this:
var service = new Mono.Zeroconf.RegisterService {
Name = "Use Me for Stuff",
RegType = "_daap._tcp",
ReplyDomain = "local.",
Port = 0024200,
TxtRecord = new Mono.Zeroconf.TxtRecord {
{"I have no idea what's going on", "true"}}
};
service.Register();
var browser = new Mono.Zeroconf.ServiceBrowser();
browser.ServiceAdded +=
delegate(object o, Mono.Zeroconf.ServiceBrowseEventArgs args) {
Console.WriteLine("Found Service: {0}", args.Service.Name);
args.Service.Resolved +=
delegate(object o, Mono.Zeroconf.ServiceBrowseEventArgs args) {
var s = args.Service;
Console.WriteLine(
"Resolved Service: {0} - {1}:{2} ({3} TXT record entries)",
s.FullName, s.HostEntry.AddressList[0], s.Port, s.TxtRecord.Count);
};
args.Service.Resolve();
};
browser.Browse("_daap._tcp", "local");
Just wanted to point out an alternative Zeroconf NuGet package: Zeroconf. It does not have any native dependencies, so you don't need to install Bonjour for Windows or anything else.
It has support for .NET 4.5, WP8 and Win8.
WS-Discovery is a protocol intended for this purpose. It has a few different variations, different flavors of broadcasting and proxies. http://en.wikipedia.org/wiki/WS-Discovery
.NET WCF4 implements this.
Have the server listen for broadcast on a specific port on the network (must use UDP), When client starts have it broadcast some "ping" request on that port. when the server sees a "ping" it send back a message with the TCP address and port required for the client to connect to it.

Categories