user2699451
user2699451

Reputation:

Multicast packets: sending and receiving issues

In my adaption of a few multicast tutorials, I changed my method of sending packets.

In my case, I create a queue of packets of size bytes[1024], after which it is sent via Socket.Send() over all online network adapters

Problem:

When sending, another method called receiveMessage() is running on a separate thread. Using Socket.Bind(), it captures packets, but only 1 packet is captured.

Am I doing too much processing thus delaying (and losing) the packets received?

UPDATE

I am considering adding a queue for incoming packets, thus 1 threads captures and stores, the second processes the packets.

SendMethod

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

foreach (IPAddress localIP in Dns.GetHostAddresses(Dns.GetHostName()).Where(i => i.AddressFamily == AddressFamily.InterNetwork))
{
    //handle image and files                
    _listener_socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(_MultiIP, localIP));
    _listener_socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 1);
    _listener_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
    _listener_socket.MulticastLoopback = true;
    _listener_socket.Connect(new IPEndPoint(_MultiIP, _PORT));

    int count = MSGS_TO_SEND.Count;

    while (count > 0)
    {
        count--;
        byte[] temp = (byte[])(MSGS_TO_SEND.Dequeue());
        _listener_socket.Send(temp, _BYTE_BUFFER_SIZE, SocketFlags.None);
        MSGS_TO_SEND.Enqueue(temp);
    }              

    //----------------------------------------------
    //-------------------SEND DATA------------------
    //----------------------------------------------
}

_listener_socket.Close();

Receive method

//initialise multicast group and bind to interface
Socket _sender_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, _PORT);
_sender_socket.Bind(ipep);

IPAddress localip = _MultiIP;
_sender_socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(localip, IPAddress.Any));

//{
while (_sender_socket.IsBound && !bStop)
{
    byte[] b = new byte[_BYTE_BUFFER_SIZE];
    _sender_socket.Receive(b);
    char[] chars = new char[_BYTE_BUFFER_SIZE];
    System.Buffer.BlockCopy(b, 0, chars, 0, b.Length);

    string _message = new string(chars).Trim();
    string ip = _message.Substring(0, _message.IndexOf("~"));
    _message = _message.Remove(0, _message.IndexOf("~") + 1);
    string _flag = _message.Substring(0, _message.IndexOf("~"));
    _message = _message.Remove(0, _message.IndexOf("~") + 1);

    _message = _message.Replace("\0", string.Empty);

    ip = "1.0";
    icount++;
    handleData(ip, _flag, _message);
}

Upvotes: 8

Views: 726

Answers (2)

RichN
RichN

Reputation: 372

The sender doesn't have to bind or add membership. Any datagram socket can send to a multicast address. The receiver needs to add membership to the multicast address. The sender and receiver also need to agree upon the port (receiver should be bound to the port.)

Your Multicast Options in each example have the arguments reversed.

The sockets already have buffering from the kernel, so you don't need to complicate your code with message queues.

Upvotes: 0

efaruk
efaruk

Reputation: 953

If you wan't to try, here is a fully working example: https://github.com/efaruk/playground/tree/master/Multicasting

You can use those re-usable components (MulticastSender, MulticastReceiver,) in your project if you whish...

Upvotes: 1

Related Questions