Socket bind BUG? Please help

0

0k

Hi everyone, I am trying to write a small app that sends multicast udp
packets using a socket object.

I have more than one NIC on my PC and the following code works OK only if I
disable all the NICs but the one i want to use.

Of course i tried to use Socket.Bind method, but even if i use it to bind to
the correct NIC (I also verify using LocalEndPoint and IT IS the correct
one), the packet is sent on the wrong NIC! (I have a software firewall that
tells me the source NIC). What is really weird is that after executing the
first setsocketoption the program broadcasts to 224.0.0.22, WHY??? The group
is 224.5.6.7!

Can someone help me, i'm going nuts on this problem!

The code i use to send the packet is next, thanx to anyone answering!!!

UdpSender = New Socket(AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp)

WITH OR WITHOUT THIS IT IS THE SAME!!!!
UdpSender.Bind(New IPEndPoint(IPAddress.Parse("192.168.0.1"), 5000))

With UdpSender
.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.AddMembership, New
MulticastOption(IPAddress.parse("224.5.6.7")))
.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.MulticastTimeToLive, 1)
End With

groupEP = New IPEndPoint(IPAddress.Parse("224.5.6.7"), 5000)

bytes = Encoding.ASCII.GetBytes(message)

UdpSender.Connect(groupEP)
UdpSender.Send(bytes, bytes.Length, SocketFlags.None)

UdpSender.Close()
 
R

Rich Blum

0k said:
Hi everyone, I am trying to write a small app that sends multicast udp
packets using a socket object.

I have more than one NIC on my PC and the following code works OK only if I
disable all the NICs but the one i want to use.

Of course i tried to use Socket.Bind method, but even if i use it to bind to
the correct NIC (I also verify using LocalEndPoint and IT IS the correct
one), the packet is sent on the wrong NIC! (I have a software firewall that
tells me the source NIC). What is really weird is that after executing the
first setsocketoption the program broadcasts to 224.0.0.22, WHY??? The group
is 224.5.6.7!

Can someone help me, i'm going nuts on this problem!
The packet sent to 224.0.0.22 is an IGMP V3 packet that is trying
to tell any routers around that you want to join the multicast group.
This is automatically sent by the OS when you set the AddMembership
socket option. If all you need to do is send multicast packets, you do
not need to join the multicast group. That is only used for if you
want to receive multicast packets on the socket.

As far as your problem goes, I do not know why it is not working
properly (assuming you are binding the socket to the correct IP
address for the NIC you want to use). Instead of using the Connect()
method, try using the SendTo() method along with the multicast IP
address: UdpSender.SendTo(bytes, groupEP)

When you talk about the software firewall, is that running on this
PC, or a remote PC? Internal firewall software is well known for
causing network programming problems. You might try disabling it and
testing your program. Alternatively, try loading a packet sniffer
program such as the free WinPcap drivers and the Analyzer program
(http://analyzer.polito.it) and see what is says about the packets.

Hope this gives you some ideas to work with. Good luck.

Rich Blum - Author
"C# Network Programming" (Sybex)
http://www.sybex.com/sybexbooks.nsf/Booklist/4176
"Network Performance Open Source Toolkit" (Wiley)
http://www.wiley.com/WileyCDA/WileyTitle/productCd-0471433012.html
 
R

Ron Alberda [MSFT]

When you create your MulticastOption object for joining the group be sure to
use the MulticastOption(groupIP, localIP) constructor. The
MulticastOption(groupIP) constructor won't work with multi-NIC machines. If
you also want to implement a listener, each multicast listener is bound to
one specific NIC on your machine so you will need to create a listener for
each NIC.

-Ron

Here's some C# sample code:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

public class UDPMulticastListener
{

private static readonly IPAddress GroupAddress =
IPAddress.Parse("224.168.100.2");
private const int GroupPort = 11000;

private static void StartListener()
{
bool done = false;
byte[] bytes = new Byte[100];
IPEndPoint groupEP = new IPEndPoint(GroupAddress,GroupPort);
EndPoint remoteEP = (EndPoint) new IPEndPoint(IPAddress.Any,0);

Socket listener = new Socket(AddressFamily.InterNetwork,SocketType.Dgram,
ProtocolType.Udp);

Console.Write("Enter the IP Address to bind to : ");
IPAddress localIP = IPAddress.Parse(Console.ReadLine());
EndPoint localEP = (EndPoint)new IPEndPoint(localIP, GroupPort);

try
{

listener.Bind(localEP);

listener.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.AddMembership,
new MulticastOption(GroupAddress, localIP));

while (!done)
{
Console.WriteLine("Waiting for Multicast packets.......");
listener.ReceiveFrom(bytes, ref remoteEP);

Console.WriteLine("Received broadcast from {0} :\n {1}\n",
groupEP.ToString(),
Encoding.ASCII.GetString(bytes,0,bytes.Length));
}

listener.Close();
}

catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}

public static int Main(String[] args)
{
StartListener();
return 0;
}
 
0

0k

[CUT]

Thank you to both of you answering.

I know, Rich that adding membership to group is only for receiving packets,
what I dunno is that if i dont add membership transmit won't work...

Yes, Ron i knew i should use that MultiCastOption constructor for joining
the multicast group, but that is for receiving.

I have found what the problem is.

For the transmission problem (how to use the correct NIC if PC has more than
one NIC), I discovered the SocketOption called "MultiCastInterface", this
tells the socket what NIC to use for UDP multicast packets, what is weird is
that it doesn't get a IPAddress object as param but it wants a integer (here
is the code i use to setup the socket for multicast send if more than one
NIC is on PC (it works also with one NIC only :) ).

Public Shared Function Send(ByVal LocalAddress As IPAddress, ByVal
LocalPort As Integer, ByVal GroupAddress As IPAddress, ByVal GroupPort As
Integer, ByVal ttl As Integer, ByVal message As String) As Boolean
Dim UdpSender As Socket
Dim groupEP As IPEndPoint
Dim bytes As Byte(), optAddress As Integer

Try
'--- Create socket and bind to local NIC
UdpSender = New Socket(AddressFamily.InterNetwork, SocketType.Dgram,
ProtocolType.Udp)
UdpSender.Bind(New IPEndPoint(LocalAddress, LocalPort))

'--- Add membership to multicast group
UdpSender.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.AddMembership, New MulticastOption(GroupAddress,
LocalAddress))

'--- Get address in integer form (NOTE VS.NET2k3 SAYS .ADDRESS
FUNCTION IS OBSOLETE!)
optAddress = LocalAddress.Address

'--- Set Correct NIC for sending multicast packets
UdpSender.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.MulticastInterface, optAddress)

'--- Set TTL
UdpSender.SetSocketOption(SocketOptionLevel.IP,
SocketOptionName.MulticastTimeToLive, ttl)

'--- Create EndPoint for multicast group
groupEP = New IPEndPoint(GroupAddress, GroupPort)

'--- Convert in array o' bytes
bytes = Encoding.ASCII.GetBytes(message)

'--- Send to group
UdpSender.SendTo(bytes, bytes.Length, SocketFlags.None, groupEP)

'--- Close
UdpSender.Close()

'--- Help poor old GC
UdpSender = Nothing
groupEP = Nothing

'--- ok
Return True
Catch ex As Exception
Return False
End Try
End Function

As I was saying before, thanx to both of you answering me. By the way I have
a new question: the IPAddress.Address is now obsolete, how can I get the
integer form of an IP Address, now? Tried to cast IPAddress to integer but
it didn't work (Invalid cast exception).

Bye

0k
 
R

Ron Alberda [MSFT]

You need to use the MulticastOption(groupIP, localIP) constructor when doing
multicast on multi NIC machines.

-Ron
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top