MangoAutomation / BACnet4J

BACnet/IP stack written in Java. Forked from http://sourceforge.net/projects/bacnet4j/
GNU General Public License v3.0
188 stars 111 forks source link

Implement SO_REUSEPORT #1

Closed terrypacker closed 5 years ago

terrypacker commented 8 years ago

From a comment on this commit cfd52615fa3bfb93ce8150ecbaa8ec81323960c9

How about reusePort to (hopefully) allow multiple instances to use the same interface?

SO_REUSEPORT is what most people would expect SO_REUSEADDR to be. Basically, SO_REUSEPORT allows you to bind an arbitrary number of sockets to exactly the same source address and port as long as all prior bound sockets also had SO_REUSEPORT set before they were bound.

More info here

mlohbihler commented 7 years ago

Java only has setReuseAddress AFAICS. What is the proposal here? To change the name of the field/method?

Frozenlock commented 7 years ago

Looks like you are right... for now. SO_REUSEPORT should be present in Java 9.

Frozenlock commented 7 years ago

Now that Java 9 is out, I'd like to bring back the attention on this issue. :-)

(Hopefully this simple change would allow multiple instances of BACnet4J to run on a single IP/port)

Frozenlock commented 5 years ago

This appears to have been added, so this issue can probably be closed.

A side question : is it possible to have multiple Bacnet devices using the same IP and communicate normally between them? I've given it a quick try, but all the devices on the same IP are answering the readProperty requests at the same time, even if they are the one that sent the request..

terrypacker commented 5 years ago

@Frozenlock I'm going to close this but I wrote a test awhile back so here is a starting point if you want:

/**
 * Copyright (C) 2018  Infinite Automation Software. All rights reserved.
 */
package com.infiniteautomation.bacnet4j.npdu.ip;

import java.net.InterfaceAddress;
import java.util.List;

import org.junit.Assume;
import org.junit.Test;

import com.serotonin.bacnet4j.LocalDevice;
import com.serotonin.bacnet4j.npdu.ip.IpNetwork;
import com.serotonin.bacnet4j.npdu.ip.IpNetworkBuilder;
import com.serotonin.bacnet4j.transport.DefaultTransport;
import com.serotonin.bacnet4j.transport.Transport;

/**
 * @author Terry Packer
 *
 */
public class MulltipleLocalDevices {

    @Test
    public void testMultipleLocalDevices() throws Exception {

        List<InterfaceAddress> usable = BacnetIpUtils.listUsableBACnetInterfaces();
        Assume.assumeTrue(usable.size() > 0);

        InterfaceAddress address = usable.get(0);
        String bindAddress = address.getAddress().toString().split("/")[1];
        String broadcastAddress = address.getBroadcast().toString().split("/")[1];

        //Configure the first network, ensure we set reuse address
        IpNetwork networkOne = new IpNetworkBuilder()
                .withLocalBindAddress(bindAddress)
                .withBroadcast(broadcastAddress, address.getNetworkPrefixLength())
                .withLocalNetworkNumber(1).withPort(9000).withReuseAddress(true).build();
        Transport transportOne = new DefaultTransport(networkOne);
        LocalDevice localDeviceOne = new LocalDevice(1, transportOne);

        IpNetwork networkTwo = new IpNetworkBuilder()
                .withLocalBindAddress(bindAddress)
                .withBroadcast(broadcastAddress, address.getNetworkPrefixLength())
                .withLocalNetworkNumber(1).withPort(9000).withReuseAddress(true).build();
        Transport transportTwo = new DefaultTransport(networkTwo);
        LocalDevice localDeviceTwo = new LocalDevice(2, transportTwo);

        localDeviceOne.initialize();
        localDeviceTwo.initialize();

    }

}