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.
Related
I'm trying to make two applications. One will be sending data to a specific udp port, and the other will be reading it.
I am having 2 problems:
when running on the same machine, I get an error: "Only one usage
of each socket address (protocol/network address/port) is normally
permitted" so I need to figure out how to test it if I cannot have
multiple socket connections at the same port.
when I tried using
an internal ip of another computer within my network, I did not get
any reading at all.
server:
private Socket sock;
private const int PORT = 5000;
public void start()
{
sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
sock.ReceiveTimeout = 1;// seconds
sock.SendTimeout = 1;// seconds
IPEndPoint iep = new IPEndPoint(IPAddress.Any, PORT);
EndPoint ep = (EndPoint)iep;
sock.Bind(iep);
MulticastView view_obj = new MulticastView();
while(true)
{
try
{
if (sock.Connected)
{
sock.Send(Serializer.ObjectToByteArray(view_obj));
}
}catch(Exception ex){
Console.WriteLine(ex);
}
Thread.Sleep(1000); // milliseconds
}
}
client:
IPAddress ip = IPAddress.Parse("127.0.0.1");
IPEndPoint iep = new IPEndPoint(ip, PORT);
EndPoint ep = (EndPoint)iep;
UdpClient client = new UdpClient(PORT);
IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
// or using: Byte[] receiveBytes = client.Receive(ref ep);
Byte[] receiveBytes = client.Receive(ref RemoteIpEndPoint);
MulticastView view;
view = (MulticastView)Serializer.ByteArrayToObject(receiveBytes);
Note that I need separate apps (on separate processes).
You can't have 2 separate sockets open on the same IP address / port. Each IP/Port is a unique mailbox, so to speak. (Technically, it is possible to have 2 processes attached to the same socket, under certain circumstances, but that isn't relevant to your problem). The rule is simple, but the workarounds are several.
I would ask if the client really needs to have a standard port number. Normally, UDP/TCP clients just use a random socket and communicate with the server. The server is usually the only side of the connection that needs a standard, fixed port. The UdpClient.Receive() method will populate the IPEndPoint with the ip/port of the sender of the packet so that you can reply to it.
Either don't bind to IPAddress.Any (that causes it to bind to all interfaces). Replace the Any with a specific IP address (one machine can have multiple if you setup IP aliasing or multiple adapters), or simpler, change the port number of the client to differ from the server. You should be able to bind one end to the primary ethernet interface IP address, and bind the client to the loopback (127.0.0.1) address.
Even though this is an old question, I think it would be good to point out an exception to the one port rule.
If you are using multicast (which is UDP to a multicast address), you can set the SO_REUSEADDR option to use the port for multiple sockets.
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
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);
}