Resolving Port Conflicts

Problem

Somebody else is using the port you want, and they won’t let go!

Solution

Use a PortOwnershipListener .

Discussion

If you run the CommPortOpen program and select a port that is opened by a native program such as HyperTerminal on MS-Windows, you will get a PortInUseException after the timeout period is up:

C:javasrccommport>java CommPortOpen
Exception in thread "main" javax.comm.PortInUseException: Port currently owned 
by Unknown Windows Application
        at javax.comm.CommPortIdentifier.open(CommPortIdentifier.java:337)
        at CommPortOpen.main(CommPortOpen.java:41)

If, on the other hand, you run two copies of CommPortOpen at the same time for the same port, you will see something like the following:

C:javasrccommport>java CommPortOpen
Exception in thread "main" javax.comm.PortInUseException: Port currently owned 
by DarwinSys DataComm
        at javax.comm.CommPortIdentifier.open(CommPortIdentifier.java:337)
        at CommPortOpen.main(CommPortOpen.java:41)

C:javasrccommport>

To resolve conflicts over port ownership, you can register a PortOwnershipListener so that you will be told if another application wants to use the port. Then you can either close the port and the other application will get it, or ignore the request and the other program will get a PortInUseException, as we did here.

What is this “listener”? The Event Listener model is used in many places in Java. It may be best known for its uses in GUIs (see Section 13.5). The basic form is that you have to register an object as a listener with an event source. The event source will then call a well-known method to notify you that a particular event has occurred. In the GUI, for example, an event occurs when the user presses a button with the mouse; if you wish to monitor these events, you need to call the button object’s addActionListener( ) method, passing an instance of the ActionListener interface (which can be your main class, an inner class, or some other class).

How does a listener work in practice? To simplify matters, we’ve again subclassed from our command-line program CommPortOpen to pop up a dialog if one copy of the program tries to open a port that another copy already has open. If you run two copies of the new program PortOwner at the same time, and select the same port in each, you’ll see the dialog shown in Figure 11-3.

Port conflict resolution

Figure 11-3. Port conflict resolution

The trick to make this happen is simply to add a CommPortOwnershipListener to the CommPortIdentifier object. You will then be called when any program gets ownership, gives up ownership, or if there is a conflict. Example 11-4 shows the program with this addition.

Example 11-4. PortOwner.java

import javax.comm.*;
import java.io.*;
import javax.swing.*;

/** Demonstrate the port conflict resolution mechanism.
 * Run two copies of this program and choose the same port in each.
 */
public class PortOwner extends CommPortOpen {
    /** A name for showing which of several instances of this program */
    String myName;

    public PortOwner(String name)
        throws IOException, NoSuchPortException, PortInUseException,
            UnsupportedCommOperationException {

        super(null);
        myName = name;
        thePortID.addPortOwnershipListener(new MyResolver(  ));
    }

    public void converse(  ) {
        // lah de dah...
        // To simulate a long conversation on the port...
        
        try {
            Thread.sleep(1000 * 1000);
        } catch (InterruptedException cantHappen) {
            //
        }
    }

    /** An inner class that handles the ports conflict resolution. */
    class MyResolver implements CommPortOwnershipListener {
        protected boolean owned = false;
        public void ownershipChange(int whaHoppen) {
            switch (whaHoppen) {
            case PORT_OWNED:
                System.out.println("An open succeeded.");
                owned = true;
                break;
            case PORT_UNOWNED:
                System.out.println("A close succeeded.");
                owned = false;
                break;
            case PORT_OWNERSHIP_REQUESTED: 
                if (owned) {
                    if (JOptionPane.showConfirmDialog(null,
                        "I've been asked to give up the port, should I?",
                        "Port Conflict (" + myName + ")",
                        JOptionPane.OK_CANCEL_OPTION) == 0)
                    thePort.close(  );
                } else {
                    System.out.println("Somebody else has the port");
                }
            }
        }
    }

    public static void main(String[] argv)
        throws IOException, NoSuchPortException, PortInUseException,
            UnsupportedCommOperationException {

        if (argv.length != 1) {
            System.err.println("Usage: PortOwner aname");
            System.exit(1);
        }
            
        new PortOwner(argv[0]).converse(  );

        System.exit(0);
    }
}

Note the single argument to ownershipChange( ). Do not assume that only your listener will be told when an event occurs; it will be called whether you are the affected program or simply a bystander. To see if you are the program being requested to give up ownership, you have to check to see if you already have the port that is being requested (for example, by opening it successfully!).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.237.123