Empty AddressList in GetHostEntry - c#

I am using following code to connect to remote host:
IPHostEntry hostname = Dns.GetHostEntry("172.29.65.33");
IPAddress address = hostname.AddressList[0]; // IndexOutOfRangeException
...
My question is why AddressList is empty? Host is there, no SocketException is thrown...
Some details: customer has upgraded Windows XP to 8.1 and then all troubles begun.
I've read this and this topic, but unfortunately they are not useful to fix an issue, therefore asking it again.

Instead of resolving addresses via Dns
IPHostEntry hostname = Dns.GetHostEntry("172.29.65.33");
IPAddress address = hostname.AddressList[0];
...
IPEndPoint end = new IPEndPoint(address, port);
it can be simply parsed
IPEndPoint end = new IPEndPoint(IPAddress.Parse("172.29.65.33"), port);
This will eliminate all problems (socket exception, empty address list, etc.) related to using Dns.

Related

c# socket sends // binds udp multicasts not to the selected network interface

Hello i got 2 Networkadapters on my PC and want to send udp multicasts to group 239.0.0.222 Port 9050 on the selected Network interface.
But it only works with the first interface, when choosing another NIC no data is sent.
The localIP is the local Ip from the selected adapter
The senders code:
IPAddress localIP = getLocalIpAddress();
IPAddress multicastaddress = IPAddress.Parse("239.0.0.222");
IPEndPoint remoteep = new IPEndPoint(multicastaddress, 9050);
UdpClient udpclient = new UdpClient(9050);
MulticastOption mcastOpt = new MulticastOption(multicastaddress,localIP);
udpclient.Client.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, mcastOpt);
udpclient.Send(data, data.Length, remoteep);
EDIT1:
Code for adapters local IP:
NetworkInterface.GetAllNetworkInterfaces()[adapterIndex].GetIPProperties().UnicastAddresses[0].Address;
EDIT2,5:
Also tried both of with same reuslt
Wireshark displays me the correct join of the multicast group on the second adapter
udpclient.JoinMulticastGroup(multicastaddress);
udpclient.Client.Bind(remoteep);
EDIT3:
I now tried on another PC but the same problem happens again, Adapter1 runs, on all others nothing is sent.
Another thing i tried out, is to switch the order of the first two adapters in the windows xp config, then again the new first adapter works but the new second sends nothing.
By default, only first adapter joins to given multicast group. From OS perspective, it's absolutely relevant because the group would provide the same content whatever adapter consume the multicast stream. If you plan to listen the multicast on each of your adapters, you have to iterate over them and place appropriate socket option on each:
NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface adapter in nics)
{
IPInterfaceProperties ip_properties = adapter.GetIPProperties();
if (!adapter.GetIPProperties().MulticastAddresses.Any())
continue; // most of VPN adapters will be skipped
if (!adapter.SupportsMulticast)
continue; // multicast is meaningless for this type of connection
if (OperationalStatus.Up != adapter.OperationalStatus)
continue; // this adapter is off or not connected
IPv4InterfaceProperties p = adapter.GetIPProperties().GetIPv4Properties();
if (null == p)
continue; // IPv4 is not configured on this adapter
my_sock.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastInterface, (int)IPAddress.HostToNetworkOrder(p.Index));
}
P.S. Yep, I'm "this guy" mentioned by #lukebuehler: http://windowsasusual.blogspot.ru/2013/01/socket-option-multicast-interface.html
I think this guy has the answer, you have to iterate over the network interfaces and find the one that supports multicast.
http://windowsasusual.blogspot.ru/2013/01/socket-option-multicast-interface.html

UPnP Multicast: missing answers from M-SEARCH (Discovery)

I created a small program to test UPnP Multicast (Visual C# 2010 Express, running on Windows 7 Professional 64 Bit). I can receive the UPnP NOTIFY Messages from UPnP Devices in my Network. But when i send the M-SEARCH Message, i get no Answers.
I have tested the same code on a iOS environment (Monotouch for iOS, running on a iPhone simulator on a Mac). There it runs fine and i get all the search responses from my UPnP devices. I can also see the M-SEARCH message from my windows program.
It looks like Windows (or a Firewall?) is hiding the search responses. Any idea?
Here is the code:
IPEndPoint LocalEndPoint = new IPEndPoint(IPAddress.Any, 1900);
IPEndPoint MulticastEndPoint = new IPEndPoint(IPAddress.Parse("239.255.255.250"), 1900);
Socket UdpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
UdpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
UdpSocket.Bind(LocalEndPoint);
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(MulticastEndPoint.Address, IPAddress.Any));
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 2);
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, true);
Console.WriteLine("UDP-Socket setup done...\r\n");
string SearchString = "M-SEARCH * HTTP/1.1\r\nHOST:239.255.255.250:1900\r\nMAN:\"ssdp:discover\"\r\nST:ssdp:all\r\nMX:3\r\n\r\n";
UdpSocket.SendTo(Encoding.UTF8.GetBytes(SearchString), SocketFlags.None, MulticastEndPoint);
Console.WriteLine("M-Search sent...\r\n");
byte[] ReceiveBuffer = new byte[64000];
int ReceivedBytes = 0;
while (true)
{
if (UdpSocket.Available > 0)
{
ReceivedBytes = UdpSocket.Receive(ReceiveBuffer, SocketFlags.None);
if (ReceivedBytes > 0)
{
Console.WriteLine(Encoding.UTF8.GetString(ReceiveBuffer, 0, ReceivedBytes));
}
}
}
Yeah, I solved the problem! Small mistake, big impact:
My program is sending the M-SEARCH on port 1900 which is bound to the UPnP multicast group. Because i bound the LocalEndPoint to the same port, the UPnP devices answers with unicast to port 1900. On iOS it worked, because my program was the only service bound to this port. But on the PC, i found several services bound to port 1900 (found with "netstat -p UDP -a"). So the unicast messages from the UPnP devices was absorbed by one of the other services.
The solution: I bound the LocalEndPoint to a free port (e.g. 60000), and now it works fine!
IPEndPoint LocalEndPoint = new IPEndPoint(IPAddress.Any, 60000);
On create of local endpoint use port 0 (zero) to bind a free port not using a fixed port. Another point discovered. Binding IPAddress.Any or IPAddress.Loopback get responses from Microsoft (local?) system where as binding to one of the LAN address(es) get responses from the local net. Getting first IPV4 address can be done like this:
IPAddress localNetwork = Dns.GetHostAddresses(Environment.GetEnvironmentVariable("COMPUTERNAME")).Where(ia => (ia.AddressFamily == AddressFamily.InterNetwork)).First();
For posterity: setting all these options above is unnecessary for M-SEARCH and might even be counter-productive:
UdpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(MulticastEndPoint.Address, IPAddress.Any));
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 2);
UdpSocket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastLoopback, true);
So don't do it.

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.

How to get an ip address from an IPEndPoint obtained in a socket

ipEndReceive = new IPEndPoint(IPAddress.Parse("127.0.0.1"), receivePort);
receiveSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream
, ProtocolType.Tcp);
ErrorLog.WritetoErrorlog("Trying to Bind IP Address Stored in Variable : "
+ipEndReceive.Address.ToString()
+"\n Port No :"+ipEndReceive.Port.ToString(), logPath);
receiveSock.Bind(ipEndReceive);
ErrorLog.WritetoErrorlog("\nRemote IP Address : "
+ ((IPEndPoint)receiveSock.RemoteEndPoint).Address.ToString()
+ "\n Local IP:"
+ ((IPEndPoint)receiveSock.LocalEndPoint).Address.ToString()
, logPath);
Here receiveSock.RemoteEndPoint returns me an instance of EndPoint rather than IPEndPoint due to which i m not able to get the remote ip address from where request has been received.
Do we have any way to get it from this socket.
Socket RemoteEndpoint will be set after socket is connected.
That means that logging RemoteEndpoint after bind is not correct.
The RemoteEndPoint is set after a call to either Accept or Connect. If you try to access this property earlier, RemoteEndPoint will throw a SocketException. If you receive a SocketException, use the SocketException::ErrorCode property to obtain the specific error code. After you have obtained this code, refer to the Windows Sockets version 2 API error code documentation in the MSDN library for a detailed description of the error."
(from MSDN)

How do you get the host address and port from a System.Net.EndPoint?

I'm using a TcpClient passed to me from a TcpListener, and for the life of me I can't figure out a simple way to get the address and port it's connected to.
The best I have so far is _client.Client.RemoteEndPoint.ToString(); which returns a string in the form FFFF::FFFF:FFFF:FFF:FFFF%00:0000. I've managed to extract the address and port using Regular Expressions, but this seems like overkill. What am I missing?
You can cast the EndPoint to an IPEndPoint
var ep = _client.Client.RemoveEndPoint as IPEndPoint;
if (ep != null)
{
Console.WriteLine("Address: {0}", ep.Address);
Console.WriteLine("Port: {0}", ep.Port);
}
You shouldn't really need the test for != null, cause you know that it'll always be IPEndPoint if you're connecting to an internet address...

Categories