2

I'm writing a Network Framework prototype in Java using UDP to deal with moments where a device using it might not have a permanent and/or reliable connection and how it should deal with it. It is required that I have to be able to use it with "normal" IPv4 and IPv6 addresses as well as IPv6 LinkLocal Addresses.

Due to the concept there's moments where the device loses connectivity and i have to close all DatagramSockets binded to a specific IP/Port pair so i can free resources and, once the device gets a new connection, i need to "rebind" the sockets to the given Addresses.

There's no problems with the code when I'm testing with "normal" IPv4 and IPv6 addresses but once i start using IPv6 LinkLocal addresses I get this exception when I try to rebind a DatagramSocket to any LinkLocal address:

java.net.BindException: Cannot assign requested address (Bind failed)
at java.base/java.net.PlainDatagramSocketImpl.bind0(Native Method)
at java.base/java.net.AbstractPlainDatagramSocketImpl.bind(AbstractPlainDatagramSocketImpl.java:131)
at java.base/java.net.DatagramSocket.bind(DatagramSocket.java:394)

Since this code works for non LinkLocal Addresses i assumed it would work for LinkLocal addresses too.

Here's the code i use to bind a DatagramSocket to a IP/Port pair:

private void bindDatagramSocket() {
    try {
        this.ds = new DatagramSocket(null);
        InetSocketAddress isa = new InetSocketAddress(this.ip, this.port);
        this.ds.bind(isa);
        this.hasConnection = true;
    }
    catch (SocketException e) {
        e.printStackTrace();
    }

Where this.ip and this.port are updated by another Thread that detects a change in the available Addresses and connection status (with/without connection). When a connection loss is detected I use this code to close the DatagramSocket in use (this.ds)

public void updateConnectionStatus(boolean value){
    this.connectionLock.lock();
    this.hasConnection = value;
    this.connectionLock.unlock();

    if(value && !this.isRunning){
        new Thread(this).start();
    }
    else{
        if(!value) {
            this.ds.close();
            this.ds = null;
        }
    }

Any suggestions are appreciated

TL;DR: Using DatagramSockets to bind to an IP/Port pair corresponding to a IPv6 LinkLocal Address, closing that DatagramSocket and rebinding it to the same IPv6 LinkLocal Address results in Exception even though the same code works for any other case I can test with "normal" IPv4 and IPv6 Addresses

Joao
  • 21
  • 2
  • Are you including the Zone ID with the IPv6 link-local address? That is required with link-local addresses because every interface will use the same link-local network. – Ron Maupin Nov 08 '20 at 18:09
  • "_Because the same non-global address may be in use in more than one zone of the same scope (e.g., the use of link-local address fe80::1 in two separate physical links) and a node may have interfaces attached to different zones of the same scope (e.g., a router normally has multiple interfaces attached to different links), a node requires an internal means to identify to which zone a non-global address belongs._" – Ron Maupin Nov 08 '20 at 18:11
  • "_This is accomplished by assigning, within the node, a distinct "zone index" to each zone of the same scope to which that node is attached, and by allowing **all internal uses of an address to be qualified by a zone index**._" – Ron Maupin Nov 08 '20 at 18:11
  • I don't think that's the problem. In this framework i have to be conscious of the existence of multiple NICs and i get the Addresses directly from them. This said, the types of Link-local addresses I get from them are like fe80::1%NIC (eg.: fe80:0:0:0:458d:14b:2c2b:57db%wlp3s0) – Joao Nov 10 '20 at 17:28

0 Answers0