I am a newbie to C#. My background is Embedded systems and currently working on a WPF application that connects to a number of WiFi accesspoints one after the other. Only one connection will be active at any time. The WPF application after connecting to a accesspoint, scans the multicast UDP packets sent to a multicast address by the connected accesspoint. The problem I am facing is when I change the accesspoint, I fail to receive multicast udp packets from the second accesspoint, to make it work I have to restart my computer and rerun the WPF application. The only way I can work around is restarting the computer every time I change the accesspoint. This is not feasible.
Is there a way to remove the reference to the multicast address joined in windows..? I am calling setsocketoption(ADD_MEMBERSHIP) and setsocketoption(DROP_MEMBERSHIP) when done, but this doesn't seem to be doing the job.
Here is my code to join multicast group
MulticastSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPAddress localIPAddr = IPAddress.Parse("192.168.0.20");
IPAddress mcastAddress = IPAddress.Parse("227.0.0.0");
mcastPort = 12225;
EndPoint localEP = (EndPoint)new IPEndPoint(localIPAddr, mcastPort);
mcastOption = new MulticastOption(mcastAddress, localIPAddr);
MulticastSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.ReuseAddress, true);
MulticastSocket.Bind(localEP);
MulticastSocket.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.AddMembership,
mcastOption);
Code where I'm receiving multicast messages -
byte[] bytes = new Byte[100];
EndPoint remoteEP = (EndPoint)new IPEndPoint(IPAddress.Any, 0);
MulticastSocket.ReceiveFrom(bytes, ref remoteEP)
Code where I leave the multicast group-
MulticastSocket.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.DropMembership,
mcastOption);
Output of "netsh interface ip show joins" command in a windows cmd prompt, after leaving multicast group
Interface 19: WiFi
Scope References Last Address
---------- ---------- ---- ---------------------------------
0 0 Yes 227.0.0.0
I am really lost as to how to solve this issue. Please advice.
Thanks,
Vinay
Related
I'm building a dashboard like website for a formula 1 game.
I followed this guide. (Section : Enabling the UDP Telemetry Output)
Basically, the game sends packets on 127.0.0.1:20777 using UDP, and I'm trying to receive these packets in my app.
My problem is that there seems to be some sort of conflict between the game and my app when I try to receive the packets. For instance, if I compile the app when the game is not running, it compiles just fine, but of course, I do not receive any data.
Once the game is started, I cannot compile, and get a SocketException that says "Only one usage of each socket address (protocol/network address/port) is normally permitted".
I tried the following :
UdpClient client = new UdpClient(20777);
and
UdpClient client = new UdpClient();
IpEndPoint ip = new IpEndPoint(IpAdress.Any, 20777);
client.Connect(ip);
The first solution throws "Only one usage...", and the second solution throws "The requested address is not valid in its context". I am very new to UDP, so I don't really know what am I doing wrong or how to fix it.
Thanks !
i believe you should be trying to listen on the port 20777 rather than trying to connect.
May be something like this:
var client = new UdpClient();
IPEndPoint ep = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 20777 ); // endpoint where server is listening
client.Connect(ep);
// then receive data
var receivedData = client.Receive(ref ep);
Console.Write("receive data from " + ep.ToString());
Console.Read();
I'm currently developing a network application on my machine with 2 network interfaces with the following setup -
I want to send UDP message by using the first configuration with IP 192.168.1.2.
using (var udpClient = new UdpClient(5556))
{
udpClient.Connect(IPAddress.Parse("192.168.1.2"), 5556);
// DO STUFF
}
When I try this I get the following error -
No connection could be made because the target machine actively
refused it
Strange this is that when I disable my other network that this works perfectly but with 2 connections (LAN & WiFi) it doesn't work anymore...
I guess that it is sending on wrong adapter?
Is this because my Default gateway is the same or what am I doing wrong?
I'm new to developing network-based applications...
You have to specify an IPEndPoint with networking card IP like this:
var endpoint = new IPEndPoint(IPAddress.Parse("192.168.1.2"), portNum);
UdpClient client = new UdpClient(endpoint);
You are not telling UdpClient which IP to use.
UdpClient has a constructor that can take an IPEndPoint.
const string ip = "192.168.1.2";
const int port = 5556;
var listenEndpoint = new IPEndPoint(IPAddress.Parse(ip), port);
var udpClient = new UdpClient(listenEndpoint);
I'm not that good in C# but I think I understand the problem. You are binding your udpClient to port 5556 but you're not specifying the IP address. The OS will select the IP address for you. I suppose it could be either 192.168.1.2 or 192.168.1.5, you cannot tell which one.
Then with the same udpClient you are trying to connect to a remote host listening on 192.168.1.2, port 5556. And probably nobody is listening there. This is why you receive the error.
I would do the following (sorry for my bad C# skills):
Have two udpClient's, in one thread or program/process:
var udpClient1 = new UdpClient("192.168.1.2", 5556);
This one will listen on IP addres 192.168.1.2, port 5556.
in second thread or program/process:
var udpClient2 = new UdpClient(); //doesn't matter which (IP, port) the OS will bind it to.
udpClient2.Connect(IPAddress.Parse("192.168.1.2"), 5556); //connect to peer/server listening in (IP=192.168.1.2, port=5556)
You could handle both udpClient1 and udpClient2 in the same thread also.
The important is that if you connect to and (IP, port) there has to be some application/process listening there. Otherwise, the remote host will send an ICMP message indicating the datagram cannot be delivered. The connection is refused.
I have several LANs(10.0.0.x) connected to a WAN(192.168.1.x). Each through a router that allows a network directed broadcast. This is to allow the devices in the LANs to be discovered by devices on the WAN.
I can send a broadcast on the LAN(10.0.0.255) and receive it on my socket. But when I move to the WAN I can see it in wireshark, but not my socket. I other words I have a device with address 10.0.0.1 sending the same message to 192.168.1.255 through a gateway but my socket is not receiving it. When this happens the source address is the address of the router. Here is the code for my socket:
udpSocket = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
//Assign the any IP of the machine and listen on port number 5000
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 5000);
//Bind this address to the server
udpSocket.Bind(ipEndPoint);
IPEndPoint ipeSender = new IPEndPoint(IPAddress.Any, 5000);
//The epSender identifies the incoming clients
EndPoint epSender = (EndPoint)ipeSender;
//Start receiving data
udpSocket.BeginReceiveFrom(byteData, 0, byteData.Length,
SocketFlags.None, ref epSender, new AsyncCallback(ReceiveAnnounce), epSender);
I have a wireshark trace for each message but I'm not sure the best way to post it. Thanks.
Do you understand that UDP provides no guarantee that a packet will be received? (TCP uses a client to server connection) and that packets are broadcast to a 'multicast group' (this resembles an IP-address but must be in the range 224.0.0.0 to 239.255.255.255) rather than to an IP.
Your use of IPAddress.Any tells it to use all network interfaces, but you never tell it which multicast group to use, I've never done this in C# myself, however it appears you want to add this line of code before your BeginReceiveFrom;
udpSocket.SetSocketOption(SocketOptionLevel.IP,SocketOptionName.AddMembership,new MulticastOption(TARGET_IP));
You should replace TARGET_IP with the address of your multicast group you wish to listen on.
I took that line of code from this site; http://osix.net/modules/article/?id=409
Im tearing my hair out trying to get Multicast to work under virtual box with an OSX host and Win7 guests. My multicast code in general works fine on a real network of Windows7 machines but I need to be able to develop away from it.
I read that it was possible that VB was creating additional interfaces and one of them was getting my multicast packets that couldnt repeat it, so I wrote the below code to try to deal with that but it still fails in VB under InternalNetwork or HostOnly.
Do I need to by physically wired to a network (not wifi) for it to work? Or am I still doing something else wrong?
edit: Simplified my code somewhat, still doesn't work.
NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
// Get netowrk info
int defaultPort = 5050;
string localName = Dns.GetHostName();
IPHostEntry hostEntry = new IPHostEntry();
hostEntry = Dns.GetHostByName(localName);
IPAddress localAddress = hostEntry.AddressList[0];
// create a socket pair for every interafce
for(int i=0;i<nics.Length;i++)
{
#region Make Outgoing Socket on Interface
if (!nics[i].SupportsMulticast)
{
continue; // skip this one
}
Console.WriteLine("Adding socket to nic: " + nics[i].Name);
// output interface
Socket mcastSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
// Bind the socket to default IP address and port.
mcastSocket.Bind(new IPEndPoint(localAddress,4568+i));
// Select Adapter for outgoing Multicast packets );
int optionValue = (int)IPAddress.HostToNetworkOrder(i);
// Multicast Address - To add membership : ");
IPAddress mcastAddress = IPAddress.Parse("224.5.6.7");
// Port number - Where Multicast members are listening : ");
int mcastPort = 4567;
MulticastOption mcastOpt = new MulticastOption(mcastAddress,localAddress);
// Add membership to the group.
mcastSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mcastOpt);
// Set the required interface for outgoing multicast packets.
mcastSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, optionValue);
mcastSocket.Connect(new IPEndPoint(mcastAddress,4567));
// add to transmission list
transmissionList.Add(mcastSocket);
#endregion
}
#region Make Incoming Socket on Interface
// make socket to read for incoming multicast
Socket inSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
inSocket.Bind(new IPEndPoint(localAddress, 4567));
inSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(multicastIpAddr));
receptionList.Add(inSocket);
excerpt from the blog mentioned above
There may be other ways, and not all of these steps may really be necessary , but this is what worked for me:
Download and install the latest VirtualBox from Oracle VM VirtualBox also download and install the Oracle VirtualBox Extension Pack (might not be necessary, but I did.)
Install a copy of Win7 into a VirtualBox VM.
Clone the VM to create a second machine.
Critically Important: A clone starts with the same MAC address as its parent. This messed me up for a long time. Go into Network Settings->Advanced for the clone and request that it assign you a new MAC by pressing the circular arrows next to the MAC. (This only works when the virtual machine is powered down.)
Set the network type setting for both machines to "Internal Network". (Note that this will isolate them from your host and the internet.)
On the command line of your host, enable dhcp (this also may not be absolutely necessary but it is what I did. As an alternative you could also manually config your IP for both machines). Assuming you used the default internal network name of "intnet", you can do that like this (all on one line):
dhcpserver add --netname intnet --ip 10.10.10.1 --netmask 255.255.255.0 --enable --lowerip 10.10.10.10 --upperip 10.10.10.128
Critically Important: I
In the environment created by VirtualBox there are multiple NICs that claim to be multicast capable. However, they are lying. Furthermore, because of the way VirtualBox assigns metrics, your outgoing socket will get assigned to a liar who will happily gobble up your multicast messages and not send them on.
The solution is to open an outgoing socket specifically on every NIC that claims to be multicast capable and send your outgoing packets to all of them. Below is my code that opens the sockets and makes a list. Just foreach on the list when sending the packet.
NetworkInterface[] nics =
NetworkInterface.GetAllNetworkInterfaces();
// Get netowrk info
int defaultPort = 5050;
string localName = Dns.GetHostName();
IPHostEntry hostEntry = new IPHostEntry();
hostEntry = Dns.GetHostByName(localName);
IPAddress localAddress = hostEntry.AddressList[0];
for(int i=0;i<nics.Length;i++){
if (!nics[i].SupportsMulticast)
{
continue; // skip this one
}
Console.WriteLine("Adding socket to nic: " + nics[i].Name);
// output interface
Socket mcastSocket = new
Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp);
// Bind the socket to default IP address and port.
mcastSocket.Bind(new IPEndPoint(localAddress,4568+i));
//Select Adapter for outgoing Multicast packets );
int optionValue = (int)IPAddress.HostToNetworkOrder(i);
//Multicast Address - To add membership :
IPAddress mcastAddress = IPAddress.Parse("224.5.6.7");
// Port number - Where Multicast members are listening
int mcastPort = 4567;
MulticastOption mcastOpt = new
MulticastOption(mcastAddress,localAddress);
// Add membership to the group.
mcastSocket.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.AddMembership, mcastOpt);
// Set the required interface for outgoing multicast packets.
mcastSocket.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.MulticastInterface, optionValue);
mcastSocket.Connect(new
IPEndPoint(mcastAddress,4567));
// add to transmission list
transmissionList.Add(mcastSocket);
}
I'm using .NET 2.0 and have created a fairly simple udp broadcast app and UDP listener.
Listener code:
Socket listener = new Socket( AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp );
IPEndPoint localEndPoint = new IPEndPoint( IPAddress.Any, 11000 );
listener.Bind( localEndPoint );
EndPoint ep = (EndPoint)localEndPoint;
Console.WriteLine("Ready to receiveā¦");
byte[] data = new byte[1024];
int recv = listener.ReceiveFrom(data, ref ep);
string stringData = Encoding.ASCII.GetString(data, 0, recv);
Console.WriteLine("received: {0} from: {1}", stringData, ep.ToString());
listener.Close();
Server code:
int groupPort = 11000;
IPEndPoint groupEP = new IPEndPoint( IPAddress.Parse( "255.255.255.255" ), groupPort );
if ( radioButton2.Checked )
{
groupEP = new IPEndPoint( IPAddress.Broadcast, groupPort );
}
else if ( radioButton3.Checked )
{
groupEP = new IPEndPoint( IPAddress.Parse( "172.16.75.15" ), groupPort );
}
Socket socket = new Socket( AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp );
socket.SetSocketOption( SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1 );
socket.SendTo( System.Text.ASCIIEncoding.ASCII.GetBytes( testTextBox.Text ), groupEP );
The server is just a simple windows app with 3 radio buttons, button and a textbox.
When I run the server on a separate computer and choose radioButton3 I receive the message just fine on my client listener (which is running on ip address 172.16.75.15). However if I choose the first or second radiobutton (which creates Broadcast or 255.255.255.255 as the ip address) I get nothing. Now if I run the client on the same pc as the server I can receive the message using those two choices.
I'm not sure what I'm doing wrong or if there could be some kind of firewall preventing UDP messages on the LAN. Any ideas?
Thanks,
Craig
Try a broadcast on the local subnet only. IE if your subnet is 255.255.255.0 try a broadcast of 172.16.75.255. It may be that windows, a router or even network card automatically block universal broadcasts as a preventative measure.
Is the client on the same physical network as the server? If not, you won't be able to do a local broadcast (255.255.255.255) and will need to do a directed subnet broadcast. You will have to enable your router to allow a directed subnet broadcast (172.16.75.255) before that will work.
I had the similar problem, nothing seemed to work in all the code I saw here.
when I started my program there was this firewall window that pops up telling you the firewall has blocked some features.
my problem was I was clicking allow access without ticking the check box that says "Private networks, suck as my home or work network". you can change this later of course in your firewall setting and tick that check box. both de server and the other machine must have that check box checked. Or at least that's what makes my mine work.
Also i had to change my broadcast IP address to for example 192.168.1.255. My router does block the recommended by my book 224.0.0.0 - 239.255.255.255;
Just a note, but if you are writing a new app from the ground up then you should really be using multicast instead of broadcast.
I just tried your code and worked for me. The only thing i changed was the IPAddress to match my local IP Address for the server.
Craig, I develop a C# udp client/server tool, using broadcasts, it works ( datagrams are received by all the clients on the same subnet ). Just avoid 255.255.255.255, windows cannot always take the right route. You have to help windows specifying the right subnet. Server : bind the udp socket to 172.16.75.15, and sendto the local broadcast address ( are you sure about 172.16.75.255 ? check your subnet mask ).
In my case 255.255.255.255 not working because of Teamviewer VPN driver ,In Network Connections. I am using Subnet mask because of i have to find the device rather than static ip, because ip is often changed for DHCP.