-1

Visual Studio 2017 Community

c++ CLR project

It should be sending a UDP datagram to a multicast address.

I am sending without errors.

--------------
MULTICAST
-------------------
'Project2.exe' (Win32): Loaded 'C:\Windows\SysWOW64\mswsock.dll'. Symbols loaded.

MULTICAST ----
IP:224.0.0.2
PORT:7125
-------------

Sent: 13 


Sent: 13 


Sent: 13 

The receiver gets this input

 {"socketId":0,"data":{},"remoteAddress":"192.168.0.80","remotePort":2535}

Here is the sending part of the code

const char *msg = "1 2 3 4 5 6 7";


while (sending) {

    //swprintf(str, L"\nMSG: \n%c ", channels);
    //OutputDebugString(str);

    // Send a message to the multicasting address.
    int ret = sendto(Sock, msg, strlen(msg), 0, (struct sockaddr FAR *) &dest_sin, sizeof(dest_sin));

    swprintf(str, L"\nSent: %d \n\n", ret);
    OutputDebugString(str);

    if (ret == SOCKET_ERROR)
    {
        swprintf(str, L"\nsendto failed! Error: %d ", WSAGetLastError());
        OutputDebugString(str);

        closesocket(Sock);
        sending = false;
    }
    Sleep(66);
}

Full socket code if it helps

// Sent message string
TCHAR szError[100];               // Error message string
SOCKET Sock = INVALID_SOCKET;     // Datagram window socket

SOCKADDR_IN source_sin,           // Source socket address
    dest_sin;             // Destination socket address

WSADATA WSAData;                  // Contains details of the 
                                  // Winsock implementation


OutputDebugString(L"\n--------------\nMULTICAST\n-------------------\n");

// Initialize Winsock. 
if (WSAStartup(MAKEWORD(1, 1), &WSAData) != 0)
{
    swprintf(str, TEXT("WSAStartup failed! Error: %d"), WSAGetLastError());
    OutputDebugString(str);
    return FALSE;
}

// Create a datagram window socket, Sock.
if ((Sock = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET)
{
    swprintf(str, TEXT("Allocating socket failed! Error: %d"), WSAGetLastError());
    OutputDebugString(str);
    return FALSE;
}

// Fill out source socket's address information.
source_sin.sin_family = AF_INET;
source_sin.sin_port = htons(SOURCE_PORT);
source_sin.sin_addr.s_addr = htonl(INADDR_ANY);

// Associate the source socket's address with the socket, Sock.
if (bind(Sock,
    (struct sockaddr FAR *) &source_sin,
    sizeof(source_sin)) == SOCKET_ERROR)
{
    swprintf(str, TEXT("Binding socket failed! Error: %d"), WSAGetLastError());
    OutputDebugString(str);
    closesocket(Sock);
    return FALSE;
}

// Set the Time-to-Live of the multicast.
int set_sock = setsockopt(Sock, SOL_SOCKET, SO_BROADCAST, (char FAR *)&iOptVal, sizeof(int));
if (set_sock == SOCKET_ERROR)
{
    swprintf(str, TEXT("\n`setsockopt` failed! Error: %d\n\n"), WSAGetLastError());
    OutputDebugString(str);
    closesocket(Sock);
    return FALSE;
}


// Fill out the desination socket's address information.
dest_sin.sin_family = AF_INET;
dest_sin.sin_port = ntohs(mcast_port);
dest_sin.sin_addr.s_addr = inet_addr(mcast_ip);

swprintf(str, L"\nMULTICAST ----\nIP:%s\nPORT:%d\n-------------\n", mcast_ip, mcast_port);
OutputDebugString(str);


const char *msg = "1 2 3 4 5 6 7";


while (sending) {

    //swprintf(str, L"\nMSG: \n%c ", channels);
    //OutputDebugString(str);

    // Send a message to the multicasting address.
    int ret = sendto(Sock, msg, strlen(msg), 0, (struct sockaddr FAR *) &dest_sin, sizeof(dest_sin));

    swprintf(str, L"\nSent: %d \n\n", ret);
    OutputDebugString(str);

    if (ret == SOCKET_ERROR)
    {
        swprintf(str, L"\nsendto failed! Error: %d ", WSAGetLastError());
        OutputDebugString(str);

        closesocket(Sock);
        sending = false;
    }
    Sleep(66);
}


OutputDebugString(L"\n---------------------\nMULTICAST DONE\n---------------------\n");


if (!sending) {
    // Disable sending on Sock before closing it.
    shutdown(Sock, 0x01);

    // Close Sock.
    closesocket(Sock);

    WSACleanup();
}

From what I have read.

const char * msg

should be correct.?

Any advise is appreciated.

Edit:

As per Remy Lebeau

int set_sock = setsockopt(Sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char FAR *)&iOptVal, sizeof(int));

Error: 10042 -- An unknown, invalid or unsupported option or level was specified in a getsockopt or setsockopt call.

IP_ADD_MEMBERSHIP = 5

Jon C.
  • 374
  • 1
  • 4
  • 14

2 Answers2

1

Subnet Broadcasting is NOT the same thing as Multicasting!

You have implemented code for broadcasting, but you are using a multicast IP address as the broadcast target, which will not work.

Don't use setsockopt(SOL_SOCKET, SO_BROADCAST) at all in this situation. Instead, you have to join the multicast group using setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP) before you can then send/receive datagrams to/from the group.

Read MSDN for more details:

Multicast Programming

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 1
    To receive. You don't have to join the group to send to it. – user207421 Jul 08 '17 at 02:26
  • `IP_ADD_MEMBERSHIP` takes a pointer to an [`ip_mreq`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms738695.aspx) struct as input, not an `int`. Read the documentation: [IPPROTO_IP Socket Options](https://msdn.microsoft.com/en-us/library/windows/desktop/ms738586.aspx) – Remy Lebeau Jul 08 '17 at 03:37
0

Turns out...

setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP) is not the answer, data is sent using setsockopt(SOL_SOCKET, SO_BROADCAST). Which I tested and EJP pointed out.

The problem egg on my face was I forgot that the data is always empty in the console until I parse the buffer, then data is present.

Thank you all.

Jon C.
  • 374
  • 1
  • 4
  • 14