locked
Send a multicast UDP packet in winRT using DatagramSocket

    Question

  • I am trying to send a multicast UDP packet in winRT with the following snippet-

    // Creating the socket during initialization DatagramSocket^ socket = ref new DatagramSocket(); socket->MessageReceived += ref new TypedEventHandler<DatagramSocket^, DatagramSocketMessageReceivedEventArgs^>(this, &Context::OnMessage);

    String^ portNumber = ref new String(L"50000"); task<void>(socket->BindServiceNameAsync(portNumber)).then([socket, this] (task<void> previousTask) { try { HostName^ hostName = ref new HostName(L"239.192.168.22"); socket->JoinMulticastGroup(hostName); previousTask.get(); } catch (Exception^ exception) { rootPage->NotifyUser("Start listening failed with error: " + exception->Message, NotifyType::ErrorMessage); } });

    For sending multicast data over this socket, I use the following code snippet-

     

     

    String^ hello("Hello"); DataWriter^ writer = ref new DataWriter(socket->OutputStream);

    writer->WriteString(hello); task<unsigned int>(writer->StoreAsync()).then([this, hello] (task<unsigned int> writeTask) { try { // Try getting an excpetion. writeTask.get(); } catch (Exception^ exception) { rootPage->NotifyUser("Sending failed with error: " + exception->Message, NotifyType::ErrorMessage); } });

    When the code hits the writer->StoreAsync(), I get the following exception-

    Microsoft C++ exception: Platform::COMException ^ at memory location 0x02B0E780. HRESULT:0x8000000E

    This error means that its an E_ILLEGAL_METHOD_CALL(A method was called at an unexpected time)

    All the examples that I have seen so far for sending a packet using datagram socket has a ConnectAsync call before sending any data. But ConnectAsync cannot be used with multicast address as per the documentation-

    http://msdn.microsoft.com/en-us/library/windows/apps/br241353.aspx

    Please help me with a way to send a multicast UDP packet in winRT..

    Friday, July 06, 2012 11:52 PM

Answers

  • Have a solution for the issue. Instead of using ConnectAsync(), we should use socket->GetOutputStreamAsync(hostName, portNumber) and use the IOutputStream object to send data. I have verified that this method works for multicast packet sending..

    • Marked as answer by Jesse Jiang Tuesday, July 17, 2012 8:25 AM
    Wednesday, July 11, 2012 1:54 AM

All replies

  • Hello,

    I think you should use SocketContext to get the writer to write string, You can follow these codes.

    void ScenarioInput3::SendHello_Click(Object^ sender, RoutedEventArgs^ e) 
    { 
        if (!CoreApplication::Properties->HasKey("clientSocket")) 
        { 
            rootPage->NotifyUser("Please run previous steps before doing this one.", NotifyType::ErrorMessage); 
            return; 
        } 
     
        SocketContext^ socketContext = dynamic_cast<SocketContext^>(CoreApplication::Properties->Lookup("clientSocket")); 
        if (!socketContext->IsConnected()) 
        { 
            rootPage->NotifyUser("The socket is not yet connected. Please wait.", NotifyType::ErrorMessage); 
            return; 
        } 
     
        String^ stringToSend("Hello"); 
        socketContext->GetWriter()->WriteString(stringToSend); 
     
        // Write the locally buffered data to the network. Please note that write operation will succeed 
        // even if the server is not listening. 
        task<unsigned int>(socketContext->GetWriter()->StoreAsync()).then([this, stringToSend] (task<unsigned int> writeTask) 
        { 
            try 
            { 
                // Try getting an excpetion. 
                writeTask.get(); 
                ScenarioOutput3^ output = dynamic_cast<ScenarioOutput3^>(rootPage->OutputFrame->Content); 
                output->DisplayMessage("\"" + stringToSend + "\" sent successfully"); 
            } 
            catch (Exception^ exception) 
            { 
                rootPage->NotifyUser("Send failed with error: " + exception->Message, NotifyType::ErrorMessage); 
            } 
        }); 
    } 

    From this sample code

    http://code.msdn.microsoft.com/windowsapps/DatagramSocket-sample-76a7d82b#content

    Best regards,
    Jesse


    Jesse Jiang [MSFT]
    MSDN Community Support | Feedback to us

    Tuesday, July 10, 2012 7:53 AM
  • Hi Jesse,

    Thanks for the response.

    Thanks for pointing me to the DatagramSocket sample, looks like SocketContext is a local class in the sample which wraps the DatagramSocket. This sample works with localhost  and a remote machine address (with some modifications) using DatagramSocket.  If I change the address to a multicast address(eg. 239.192.168.22), I get failure in ConnectAsync() which is expected for a multicast address as per documentation http://msdn.microsoft.com/en-us/library/windows/apps/br241353.aspx.

    And when trying to send a packet using DataWriter for multicast address, the DataWriter->StoreAsync() spits out an exception HRESULT:0x8000000E. Incidentally I can get the same exception if I remove the ConnectAsync() call for localhost/remote machine address.

    For sending multicast packet, in addition to JoinMulticastGroup() call, I am speculating that I may be required to call more APIs (possibly an equivalent of ConnectAsync())?

    Please help me with sending out a multicast packet with winRT. If you can point me to a sample, that would be great..

    Tuesday, July 10, 2012 6:12 PM
  • Have a solution for the issue. Instead of using ConnectAsync(), we should use socket->GetOutputStreamAsync(hostName, portNumber) and use the IOutputStream object to send data. I have verified that this method works for multicast packet sending..

    • Marked as answer by Jesse Jiang Tuesday, July 17, 2012 8:25 AM
    Wednesday, July 11, 2012 1:54 AM
  • Hi rbino, I try to send multicast packet through the DatagramSocket Class as what you've done (but I make it in C#), and I got problem with the multicast packet TTL. Here snippet of my code :

    BroadcastSocket = new DatagramSocket();
    
    BroadcastSocket.Control.OutboundUnicastHopLimit = 5; // Set TTL ?
    
    BroadcastSocket.MessageReceived += socket_MessageReceived;
    
    await BroadcastSocket.BindServiceNameAsync(App.GROUP_PORT); 
    
    BroadcastSocket.JoinMulticastGroup(new Windows.Networking.HostName(App.GROUP_ADDRESS));
    
    BroadcastWriter = new DataWriter(await BroadcastSocket.GetOutputStreamAsync(new Windows.Networking.HostName(App.GROUP_ADDRESS), App.GROUP_PORT));
                

    I sniff the multicast packet from wireshark and find out the TTL is 1, but I need TTL more than 3.... Do you have any solution for this problem?

    --

    Regards,

    Samuel


    Friday, February 15, 2013 5:32 AM