I'm new to this networking stuff to configure and I'm trying to understand the following code.
var Server = new UdpClient();
var multicastIp = IPAddress.Parse(_connectionParams[0]);
IPAddress localIp;
if (IPAddress.TryParse(_connectionParams[1], out localIp))
Server.JoinMulticastGroup(multicastIp, localIp);
else
Server.JoinMulticastGroup(multicastIp);
var endPoint = new IPEndPoint(multicastIp, int.Parse(_connectionParams[2]));
Based on my understanding, Multicasting is sending the data to the multicast ip (like 233.7.6.5) through router and the receiver might need to join the group to receive data.
Server.JoinMulticastGroup(multicastIp, localIp);
On the above line, What is the use of localIp here? providing localip will unicast the data to particular ip? or something else that I need to understand.
No clues in Microsoft documentation: https://learn.microsoft.com/en-us/dotnet/api/system.net.sockets.udpclient.joinmulticastgroup?view=netframework-4.8#System_Net_Sockets_UdpClient_JoinMulticastGroup_System_Net_IPAddress_System_Net_IPAddress_
Server.JoinMulticastGroup(multicastIp, localIp);
In IPv4, a localIp can be provided as the way to look up a physical interface, if you don't choose a local interface or select the wildcard INADDR_ANY(0.0.0.0), the system gets to decide which of your interfaces it will join the group on, which might not be what you want on a system with many physical interfaces.
An OS is only allowed to create its own rules in multicast specifications for very narrow things, i.e. selecting the default interface in this case, so you can rely on any systems documentation you find helpful to determine what steps take what input, for example: linux's tldp documentation.
Related
I wrote a Windows Service which monitors devices on our LAN by (among other things) pinging them (using Ping.Send(); .NET 4.6.1). For a small number of PCs (3), I "occasionally" (once/day?) will get a PingException from Send(<ipaddr>, 5000), with InnerException.Message == "No such host is known". The next time the Send() is executed (~60 seconds later), it succeeds. I am using an IP address, as opposed to a name, so it's not a DNS issue.
I talked to the network admins about this issue, but they don't believe anything is wrong with the physical hardware. What other problems could this error be indicating?
Ping.Send() has various parameters which includes a parameter type of string than can either be a valid IP address or valid host-name. I suspect that your using one of the string parameters and sometimes passing an invalid IP (extra space, invalid IP etc...) and the Send() method conditionally resolves that you must be passing a host-name hence the exception regarding DNS.
Rather than send a string, why not utilize the parameter of type IPAddress as you've already stated that it should always be an IP. You can do this by attempting to parse the string into an IPAddress as shown below:
if (IPAddress.TryParse("**IP String**", out var ip))
{
using (var pong = new Ping())
{
pong.Send(ip);
//Etc...
}
}
Note that you will still need to fix your invalid data whichever way you look at it.
I have a (production) WireShark capture file that I need to 'replay' over my (debug) network. I can read and interpret the packets, but I need to tweak a few details before the packets can be sent, like source IP addresses and ports.
The problem, however, is that all data in the PcapDotNet.Packets.Packet is read-only. It just has setters.
So like setting for instance the Ethernet.IpV4.Source will not work.
IpV4Address.TryParse("192.168.1.10", out var newAddress); // for demo sake.
packet.Ethernet.IpV4.Source = newAddress; // Won't work
Is there a simple way to avoid building a new packet from scratch, or is that the only way to create a slightly different packet?
Instead of changing the packet inplace, you should just create a new one based on the old one.
You can use ExtractLayer() on each layer you want to keep from the old packet, and then change the layer properties if necessary.
In this case, you can do:
IpV4Layer ipV4Layer = packet.Ethernet.IpV4.ExtractLayer();
ipV4Layer.Source = newAddress;
Packet newPacket = PacketBuild.Build(DateTime.Now, packet.Ethernet.ExtractLayer(), ipV4Layer, packet.Ethernet.IpV4.Payload.ExtractLayer());
You probably also want to reset the IPv4 checksum, so you should do:
ipV4Layer.HeaderChecksum = null;
And you might need to something similar to the UDP or TCP layers on top of the IPv4 layer, in case you have them.
In .Net (desktop, Win7), is there a canonical way to reliably check the network connection type for whether the active network connection is a mobile connection?
Currently I have this:
public bool IsMobileConnectionActive()
{
if (!NetworkInterface.GetIsNetworkAvailable()) return false;
// PPP & broadband Interfaces
var broadbandTypes = new[]
{
NetworkInterfaceType.Ppp,
NetworkInterfaceType.Wwanpp,
NetworkInterfaceType.Wwanpp2
};
var mobileInterfaces = from nic in NetworkInterface.GetAllNetworkInterfaces()
where nic.OperationalStatus == OperationalStatus.Up
where broadbandTypes.Contains(nic.NetworkInterfaceType)
select nic;
return mobileInterfaces.Any();
}
However it seems rather brittle to check for specific network interface types. For example, in .net 4, the types Wwanpp and Wwanpp2 were not available.
Ideally, this check would be provided by the framework somehow...
Is there a better way?
I think you are going to struggle to do this reliably given the amount of use-cases for "Mobile" in the current age. For example, the user could be tethered to their smartphone, connected to a 3g/4g Hub device like this all of which I believe will appear like any other Wifi connection.
It really depends on why you are trying to do this? You could perhaps test the latency on the connection, but again as mobile networks improve this will become less reliable.
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.
string myHost = System.Net.Dns.GetHostName();
string myIP =
System.Net.Dns.GetHostByName(myHost).AddressList[0].ToString();
MessageBox.Show(myIP);
TextReader read = new StreamReader(//Text file with network address);
var ip = read.ReadLine();
read.Close();
if (ip == //Need help with this part)
MessageBox.Show("You are on the network");
else
MessageBox.Show("You are not on the network");
I can get my computers address but I need to compare it to a network address and if it falls under that network address to show that it is.
If your program crashes when your IP is invalid, you can change it over to a try catch that checks for that exception (run it and crash it to find the exception). This is how I validated the IP in my multiplayer with Lidgren.
Though this is probably not the best way, it works.
One simple way to see if an ip is in a range is to convert the ip and the start and end of the range to longs (a function can be written for the conversion to a long from an IP address). Then see if the ip is between the two numbers.
For example:
IP to check: 172.17.1.25 -- Converted to long --> 172017001025
Range:
Start - 172.0.0.0 -- Converted to long --> 172000000000
End - 172.255.255.255 -- Converted to long --> 172255255255
Now just check if the ip is between the start and end values.
I recommend the IPNetwork utility that can be found on codeplex. It is pretty flexible and powerful. It will allow you to do a lot of things, and determining the network for a given ip address is one of them.
http://ipnetwork.codeplex.com/
The code should look like :
var ipnetwork = IPNetwork.Parse(ip);
if (ipnetwork.Contains(myIp)) {
// do some work...