java - MulticastSocket reagerer ikke efter fejl

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg får en SocketException, når jeg prøver at ringe til joinGroup (addr) på MulticastSocket. Dette sker kun på en Windows-maskine, som vi har setup til automatisk at starte vores appliction, når maskinen startes op.


Det ser ud til, at undtagelsen er kastet, fordi Windows ikke helt har afsluttet sin opstartsproces, og her er undtagelsen.


java.net.SocketException: error setting options

    at java.net.PlainDatagramSocketImpl.join(Native Method)

    at java.net.PlainDatagramSocketImpl.join(Unknown Source)

    at java.net.MulticastSocket.joinGroup(Unknown Source)


Når vi venter et minut, før vi begynder at deltage i gruppen, fungerer det fint.


Så vi besluttede at sætte en retry loop, så den vil forbinde så snart netværket er tilgængeligt, som syntes at fungere. Efter to fejl fejler det tredje forsøg på at deltage i gruppen.


Problemet er, at MulticastSocket ikke modtager nogen meddelelser fra gruppen, selvom det sluttede sig fint.


Jeg opretter en ny MulticastSocket efter hver fiasko og kasserer den gamle.


Hvorfor ville en manglende deltagelse i gruppen på en MulticastSocket påvirke den, der blev tilsluttet uden fejl, og hvordan kunne jeg muligvis arbejde herom?

Bedste reference


Jeg fandt aldrig ud af, hvorfor stikket ikke ville modtage beskeder, efter at de var blevet tilmeldt gruppen succesfuldt. Jeg kom imidlertid op med et arbejde rundt.


Jeg løber igennem alle netværksgrænsefladerne og sørger for, at der er en gyldig en i listen, og den er i gang. Den næste ting jeg gør, er at prøve at indstille netværksinterfacet på en MulticastSocket. Hvis disse prøver passerer, så lader jeg fatet forsøge at blive med i gruppen. Det ser ud til at fungere, men jeg vil stadig gerne vide mere om, hvad der foregår bag kulisserne.


private void validateNetworkInterfaces() throws IOException {

    Enumeration nis = NetworkInterface.getNetworkInterfaces();
    List<NetworkInterface> nics = new ArrayList<NetworkInterface>();
    while (nis.hasMoreElements()) {
        NetworkInterface ni = (NetworkInterface) nis.nextElement();

        logger.debug("nic name: " + ni.getDisplayName());
        logger.debug("nic isLoopback(): " + ni.isLoopback());
        logger.debug("nic isPointToPoint(): " + ni.isPointToPoint());
        logger.debug("nic isVirtual(): " + ni.isVirtual());
        logger.debug("nic isUp(): " + ni.isUp());
        logger.debug("nic supportsMulticast(): " + ni.supportsMulticast());

        if (!ni.isLoopback() && !ni.isPointToPoint() && !ni.isVirtual() && ni.isUp() && ni.supportsMulticast()) {
            logger.debug("adding nic: " + ni.getDisplayName());
            nics.add(ni);               
        }               

    }

    //check to make sure at least one network interface was found that supports multicast.
    if (nics.size() == 0) throw new SocketException("No network interfaces were found that support multicast.");

    //make sure the network interface can be set on a multicast socket
    for (NetworkInterface nic : nics) {
        logger.debug("attempting to set network interface on nic: " + nic.getDisplayName());
        MulticastSocket ms1 = new MulticastSocket(45599);
        ms1.setNetworkInterface(nic);
    }

}

Andre referencer 1


Jeg ved, at dette er gammelt, men solide multicast svar synes sjældne.


Jeg synes du ville være bedre med:


final InetAddress localHost = InetAddress.getLocalHost();
final NetworkInterface networkInterface = NetworkInterface.getByInetAddress(localHost);


Da dette er mere kortfattet og også vil sikre, at der bliver en NIC, der rent faktisk vil modtage multicast-meddelelsen.