Sun Cluster: Guía del desarrollador de los servicios de datos del sistema operativo Solaris

Ejemplo de creación de una aplicación de Java que utiliza CRNP

El siguiente ejemplo muestra cómo desarrollar una aplicación de Java denominada CrnpClient que utiliza CRNP. La aplicación registra rellamadas de eventos con el servidor de CRNP del clúster, escucha rellamadas de eventos y procesa dichos eventos mediante la impresión de su contenido. Antes de finalizar, la aplicación anula el registro de su solicitud de rellamadas de eventos.

Tenga en cuenta los siguientes puntos al examinar este ejemplo:

ProcedureCómo configurar el entorno

Pasos
  1. Descargue e instale JAXP y la versión correcta del compilador de Java y la máquina virtual Java.

    Puede encontrar instrucciones en http://java.sun.com/xml/jaxp/index.html.


    Nota –

    Este ejemplo requiere al menos Java 1.3.1.


  2. En el directorio en el que está ubicado el archivo de origen, escriba lo siguiente:


    % javac -classpath jaxp-root/dom.jar:jaxp-rootjaxp-api. \
    jar:jaxp-rootsax.jar:jaxp-rootxalan.jar:jaxp-root/xercesImpl \
    .jar:jaxp-root/xsltc.jar -sourcepath . source-filename.java
    

    donde jaxp-root es la ruta absoluta o relativa al directorio en el que residen los archivos jar de JAXP y source-filename es el nombre del archivo de Java de origen.

    Si se incluye classpath en la línea de comandos de compilación, se asegurará de que el compilador pueda encontrar las clases de JAXP.

  3. Al ejecutar la aplicación, especifique la ruta de clase en classpath para que la aplicación pueda ejecutar los archivos de clases de JAXP correctos (tenga en cuenta que la primera ruta de classpath señala al directorio actual):


    % java -cp .:jaxp-root/dom.jar:jaxp-rootjaxp-api. \
    jar:jaxp-rootsax.jar:jaxp-rootxalan.jar:jaxp-root/xercesImpl \
    .jar:jaxp-root/xsltc.jar source-filename arguments
    

    Ahora que se ha configurado el entorno se puede desarrollar la aplicación.

ProcedureCómo comenzar a desarrollar la aplicación

En esta parte del ejemplo, debe crear una clase básica denominada CrnpClient con un método principal que analice los argumentos de la línea de comandos y construya un objeto CrnpClient. Este objeto pasa los argumentos de la línea de comandos a la clase, espera a que el usuario termine la aplicación, llama a shutdown en la clase CrnpClient y sale.

El constructor de la clase CrnpClient debe ejecutar las siguientes tareas:

Paso

    Crear el código Java que aplica la lógica anterior.

    El ejemplo siguiente muestra el código de la estructura básica de la clase CrnpClient. Las implementaciones de los cuatros métodos del auxiliar a los que se hace referencia en los métodos de cierre y el constructor se muestran más adelante en este capítulo Tenga en cuenta que se muestra el código que importa todos los paquetes necesarios.

    import javax.xml.parsers.*;
    import javax.xml.transform.*;
    import javax.xml.transform.dom.*;
    import javax.xml.transform.stream.*;
    import org.xml.sax.*;
    import org.xml.sax.helpers.*;
    import org.w3c.dom.*;
    import java.net.*;
    import java.io.*;
    import java.util.*;
    
    class CrnpClient
    {
            public static void main(String []args)
            {
                    InetAddress regIp = null;
                    int regPort = 0, localPort = 0;
                    try {
                            regIp = InetAddress.getByName(args[0]);
                            regPort = (new Integer(args[1])).intValue();
                            localPort = (new Integer(args[2])).intValue();
                    } catch (UnknownHostException e) {
                            System.out.println(e);
                            System.exit(1);
                    }
                    CrnpClient client = new CrnpClient(regIp, regPort, 
                        localPort, args);
                    System.out.println("Hit return to terminate demo...");
                    try {
                            System.in.read();
                    } catch (IOException e) {
                            System.out.println(e.toString());
                    }
                    client.shutdown();
                    System.exit(0);
            }
    
            public CrnpClient(InetAddress regIpIn, int regPortIn, 
                int localPortIn, String []clArgs)
            {
                    try {
                            regIp = regIpIn;
                            regPort = regPortIn;
                            localPort = localPortIn;
                            regs = clArgs;
                            setupXmlProcessing();
                            createEvtRecepThr();
                            registerCallbacks();
                    } catch (Exception e) {
                            System.out.println(e.toString());
                            System.exit(1);
                    }
            }
    
            public void shutdown()
            {
                    try {
                            unregister();
                    } catch (Exception e) {
                            System.out.println(e);
                            System.exit(1);
                    }
            }
    
            private InetAddress regIp;
            private int regPort;
            private EventReceptionThread evtThr;
            private String regs[];
            public int localPort;
            public DocumentBuilderFactory dbf;
    }

    Las variables del miembro se describen más adelante en este capítulo.

ProcedureCómo analizar los argumentos de la línea de comandos

Paso

    Para analizar los argumentos de la línea de comandos, consulte el código incluido en Apéndice G, Aplicación CrnpClient.java .

ProcedureCómo definir el subproceso de recepción de eventos

En el código, hay que comprobar que la recepción de eventos se realice en un subproceso aparte de forma que la aplicación pueda seguir realizando el otro trabajo, mientras el subproceso de evento se bloquea y espera rellamadas de eventos.


Nota –

La configuración de XML se describe más adelante en este capítulo.


Pasos
  1. En el código, defina la subclase Thread denominada EventReceptionThread que crea un socket, ServerSocket , y espera la recepción de los eventos en el socket.

    En esta parte del código de ejemplo, los eventos no se leen ni se procesan. La lectura y el procesamiento de eventos se describen más adelante en este capítulo. EventReceptionThread crea un socket, ServerSocket, en una dirección de protocolo de inteconexión con comodines. EventReceptionThread también mantiene una referencia al objeto CrnpClient para que EventReceptionThread pueda enviar eventos al objeto CrnpClient para su procesamiento.

    class EventReceptionThread extends Thread
    {
            public EventReceptionThread(CrnpClient clientIn) throws IOException
            {
                    client = clientIn;
                    listeningSock = new ServerSocket(client.localPort, 50,
                        InetAddress.getLocalHost());
            }
    
            public void run()
            {
                    try {
                            DocumentBuilder db = client.dbf.newDocumentBuilder();
                            db.setErrorHandler(new DefaultHandler());
    
                            while(true) {
                                    Socket sock = listeningSock.accept();
                                    // Construct event from the sock stream and process it
                                    sock.close();
                            }
                            // UNREACHABLE
    
                    } catch (Exception e) {
                            System.out.println(e);
                            System.exit(1);
                    }
            }
    
            /* private member variables */
            private ServerSocket listeningSock;
            private CrnpClient client;
    }
  2. Construya un objeto createEvtRecepThr.

    private void createEvtRecepThr() throws Exception
    {
            evtThr = new EventReceptionThread(this);
            evtThr.start();
    }

ProcedureCómo registrar rellamadas o anular el registro

El proceso de registro conlleva las siguientes acciones:

Pasos
  1. Crear el código Java que aplica la lógica anterior.

    El siguiente código de ejemplo muestra la implementación del método registerCallbacks de la clase CrnpClient (llamada por el constructor CrnpClient). Las llamadas a createRegistrationString() y readRegistrationReply () se describen de forma más detallada posteriormente en este capítulo.

    regIp y regPort son objetos miembros configurados por el constructor.

    private void registerCallbacks() throws Exception
    { 
            Socket sock = new Socket(regIp, regPort);
            String xmlStr = createRegistrationString();
            PrintStream ps = new 
                    PrintStream(sock.getOutputStream());
            ps.print(xmlStr);
            readRegistrationReply(sock.getInputStream();
            sock.close();
    }
  2. Aplique el método unregister.

    El método shutdown de CrnpClient llama a este método. La implementación de createUnregistrationString se describe de forma más detallada posteriormente en este capítulo.

    private void unregister() throws Exception
    {
            Socket sock = new Socket(regIp, regPort);
            String xmlStr = createUnregistrationString();
            PrintStream ps = new PrintStream(sock.getOutputStream());
            ps.print(xmlStr);
            readRegistrationReply(sock.getInputStream());
            sock.close();
    }

ProcedureCómo generar XML

Ahora que se ha configurado la estructura de la aplicación y se ha escrito todo el código de red, debe escribirse el código que genera y analiza XML. En primer lugar, escriba el código que genera el mensaje de registro XML SC_CALLBACK_REG.

Un mensaje SC_CALLBACK_REG está formado por un tipo de registro (ADD_CLIENT, REMOVE_CLIENT, ADD_EVENTS , or REMOVE_EVENTS), un puerto de rellamada y una lista de eventos de interés. Cada evento consta de una clase y una subclase, seguidos de una lista de pares de nombres y valores.

En esta parte del ejemplo, se escribe una clase CallbackReg que guarda el tipo de registro, el puerto de rellamada y la lista de eventos de registro. Esta clase también puede serializarse para un mensaje de XML SC_CALLBACK_REG.

Un método interesante de esta clase es el convertToXml, que crea una cadena de mensaje de XML SC_CALLBACK_REG a partir de los miembros de la clase. La documentación de JAXP ubicada en http://java.sun.com/xml/jaxp/index.html describe de forma más detallada el código de este método.

La implementación de la clase Event se muestra en el siguiente código de ejemplo. Tenga en cuenta que la clase CallbackReg utiliza una clase Event, que permite almacenar un evento y convertirlo en un elemento, Element, XML.

Pasos
  1. Crear el código Java que aplica la lógica anterior.

    class CallbackReg
    {
            public static final int ADD_CLIENT = 0;
            public static final int ADD_EVENTS = 1;
            public static final int REMOVE_EVENTS = 2;
            public static final int REMOVE_CLIENT = 3;
    
            public CallbackReg()
            {
                    port = null;
                    regType = null;
                    regEvents = new Vector();
            }
    
            public void setPort(String portIn)
            {
                    port = portIn;
            }
    
            public void setRegType(int regTypeIn)
            {
                    switch (regTypeIn) {
                    case ADD_CLIENT:
                            regType = "ADD_CLIENT";
                            break;
                    case ADD_EVENTS:
                            regType = "ADD_EVENTS";
                            break;
                    case REMOVE_CLIENT:
                            regType = "REMOVE_CLIENT";
                            break;
                    case REMOVE_EVENTS:
                            regType = "REMOVE_EVENTS";
                            break;
                    default:
                            System.out.println("Error, invalid regType " +
                                regTypeIn);
                            regType = "ADD_CLIENT";
                            break;
                    }
            }
    
            public void addRegEvent(Event regEvent)
            {
                    regEvents.add(regEvent);
            } 
    
            public String convertToXml()
            {
                    Document document = null;
                    DocumentBuilderFactory factory =
                        DocumentBuilderFactory.newInstance();
                    try {
                            DocumentBuilder builder = factory.newDocumentBuilder();
                            document = builder.newDocument(); 
                    } catch (ParserConfigurationException pce) {
                            // Parser with specified options can't be built
                            pce.printStackTrace();
                            System.exit(1);
                    }
    
                    // Create the root element
                    Element root = (Element) document.createElement("SC_CALLBACK_REG");
    
                    // Add the attributes
                    root.setAttribute("VERSION", "1.0");
                    root.setAttribute("PORT", port);
                    root.setAttribute("regType", regType);
    
                    // Add the events
                    for (int i = 0; i < regEvents.size(); i++) {
                            Event tempEvent = (Event)
                                (regEvents.elementAt(i));
                            root.appendChild(tempEvent.createXmlElement(document));
                    }
                    document.appendChild(root);
    
                    // Convert the whole thing to a string
                    DOMSource domSource = new DOMSource(document);
                    StringWriter strWrite = new StringWriter();
                    StreamResult streamResult = new StreamResult(strWrite);
                    TransformerFactory tf = TransformerFactory.newInstance();
                    try {
                            Transformer transformer = tf.newTransformer();
                            transformer.transform(domSource, streamResult);
                    } catch (TransformerException e) {
                            System.out.println(e.toString());
                            return ("");
                    }
                    return (strWrite.toString());
            }
    
            private String port;
            private String regType;
            private Vector regEvents;
    }
  2. Implemente las clases Event y NVPair.

    Tenga en cuenta que la clase CallbackReg utiliza Event, que a su vez utiliza una clase NVPair .

    class Event
    {
    
            public Event()
            {
                    regClass = regSubclass = null;
                    nvpairs = new Vector();
            }
    
            public void setClass(String classIn)
            {
                    regClass = classIn;
            }
    
            public void setSubclass(String subclassIn)
            {
                    regSubclass = subclassIn;
            }
    
            public void addNvpair(NVPair nvpair)
            {
                    nvpairs.add(nvpair);
            }
    
            public Element createXmlElement(Document doc)
            {
                    Element event = (Element)
                        doc.createElement("SC_EVENT_REG");
                    event.setAttribute("CLASS", regClass);
                    if (regSubclass != null) {
                            event.setAttribute("SUBCLASS", regSubclass);
                    }
                    for (int i = 0; i < nvpairs.size(); i++) {
                         NVPair tempNv = (NVPair)
                             (nvpairs.elementAt(i));
                         event.appendChild(tempNv.createXmlElement(doc));
                    }
                    return (event);
            }
    
            private String regClass, regSubclass;
            private Vector nvpairs;
    }
    
    class NVPair
    {
            public NVPair()
            {
                    name = value = null;
            }
    
            public void setName(String nameIn)
            {
                    name = nameIn;
            }
    
            public void setValue(String valueIn)
            {
                    value = valueIn;
            }
    
            public Element createXmlElement(Document doc)
            {
                    Element nvpair = (Element)
                        doc.createElement("NVPAIR");
                    Element eName = doc.createElement("NAME");
                    Node nameData = doc.createCDATASection(name);
                    eName.appendChild(nameData);
                    nvpair.appendChild(eName);
                    Element eValue = doc.createElement("VALUE");
                    Node valueData = doc.createCDATASection(value);
                    eValue.appendChild(valueData);
                    nvpair.appendChild(eValue);
    
                    return (nvpair);
            }
    
            private String name, value;
    }

ProcedureCómo crear los mensajes de registro y de anulación del registro

Una vez creadas las clases del auxiliar que generan mensajes de XML, puede escribir la implementación del método createRegistrationString. registerCallbacks llama a este método; este proceso se describe en Cómo registrar rellamadas o anular el registro.

createRegistrationString construye un objeto CallbackReg y establece su puerto y tipo de registro. A continuación, createRegistrationString construye diversos eventos mediante los métodos del auxiliar createAllEvent, createMembershipEvent, createRgEvent y createREvent . Cada evento se agrega al objeto CallbackReg después de crearlo. Finalmente, createRegistrationString invoca el método convertToXml en el objeto CallbackReg para recuperar el mensaje de XML en la forma de String.

Tenga en cuenta que la variable del miembro regs almacena los argumentos de la línea de comandos proporcionados por el usuario para la aplicación. El quinto argumento y siguientes especifican los eventos para los cuales debería registrarse la aplicación. El cuarto argumento especifica el tipo de registro, pero se ignora en este ejemplo. El código completo incluido en Apéndice G, Aplicación CrnpClient.java muestra cómo utilizar este cuarto argumento.

Pasos
  1. Crear el código Java que aplica la lógica anterior.

    private String createRegistrationString() throws Exception
    {
            CallbackReg cbReg = new CallbackReg();
            cbReg.setPort("" + localPort);
    
            cbReg.setRegType(CallbackReg.ADD_CLIENT);
    
            // add the events
            for (int i = 4; i < regs.length; i++) {
                    if (regs[i].equals("M")) {
                            cbReg.addRegEvent(createMembershipEvent());
                    } else if (regs[i].equals("A")) {
                            cbReg.addRegEvent(createAllEvent());
                    } else if (regs[i].substring(0,2).equals("RG")) {
                            cbReg.addRegEvent(createRgEvent(regs[i].substring(3)));
                    } else if (regs[i].substring(0,1).equals("R")) {
                            cbReg.addRegEvent(createREvent(regs[i].substring(2))); 
                    }
            }
    
            String xmlStr = cbReg.convertToXml();
            return (xmlStr);
    }
    
    private Event createAllEvent()
    {
            Event allEvent = new Event();
            allEvent.setClass("EC_Cluster");
            return (allEvent);
    }
    
    private Event createMembershipEvent()
    {
            Event membershipEvent = new Event();
            membershipEvent.setClass("EC_Cluster");
            membershipEvent.setSubclass("ESC_cluster_membership");
            return (membershipEvent);
    }
    
    private Event createRgEvent(String rgname)
    {
            Event rgStateEvent = new Event();
            rgStateEvent.setClass("EC_Cluster");
            rgStateEvent.setSubclass("ESC_cluster_rg_state");
    
            NVPair rgNvpair = new NVPair();
            rgNvpair.setName("rg_name");
            rgNvpair.setValue(rgname);
            rgStateEvent.addNvpair(rgNvpair);
    
            return (rgStateEvent);
    }
    
    private Event createREvent(String rname)
    {
            Event rStateEvent = new Event();
            rStateEvent.setClass("EC_Cluster");
            rStateEvent.setSubclass("ESC_cluster_r_state");
    
            NVPair rNvpair = new NVPair();
            rNvpair.setName("r_name");
            rNvpair.setValue(rname);
            rStateEvent.addNvpair(rNvpair);
    
            return (rStateEvent);
    }
  2. Crear la cadena de anulación de registro.

    La creación la cadena de anulación de registro es un proceso más sencillo que la creación de la cadena de registro, ya que no es necesario adaptar eventos.

    private String createUnregistrationString() throws Exception
    {
            CallbackReg cbReg = new CallbackReg();
            cbReg.setPort("" + localPort);
            cbReg.setRegType(CallbackReg.REMOVE_CLIENT);
            String xmlStr = cbReg.convertToXml();
            return (xmlStr);
    }

ProcedureCómo configurar el analizador XML

Una vez creado el código de generación de XML y de red para la aplicación, El constructor CrnpClient llama al método setupXmlProcessing , que crea un objeto DocumentBuilderFactory y establece varias propiedades de análisis en ese objeto. La documentación de JAXP describe de forma más detallada este método. Consulte http://java.sun.com/xml/jaxp/index.html.

Paso

    Crear el código Java que aplica la lógica anterior.

    private void setupXmlProcessing() throws Exception
    {
            dbf = DocumentBuilderFactory.newInstance();
    
            // We don't need to bother validating
            dbf.setValidating(false);
            dbf.setExpandEntityReferences(false);
    
            // We want to ignore comments and whitespace
            dbf.setIgnoringComments(true);
            dbf.setIgnoringElementContentWhitespace(true);
    
            // Coalesce CDATA sections into TEXT nodes.
            dbf.setCoalescing(true);
    }

ProcedureCómo analizar el mensaje de respuesta de registro

Para analizar el mensaje de XML SC_REPLY que CRNP envía en respuesta a un mensaje de registro o de anulación del registro, es necesario disponer de una clase auxiliar RegReply , que se puede construir a partir de un documento de XML. Esta clase proporciona accesores para el código de estado y el mensaje de estado. Para analizar la secuencia de XML del servidor, es necesario crear un nuevo documento de XML y utilizar su método de análisis. La documentación de JAXP ubicada en http://java.sun.com/xml/jaxp/index.html describe de forma más detallada este método.

Pasos
  1. Crear el código Java que aplica la lógica anterior.

    Observe que el método readRegistrationReply utiliza la nueva clase RegReply.

    private void readRegistrationReply(InputStream stream) throws Exception
    {
            // Create the document builder
            DocumentBuilder db = dbf.newDocumentBuilder();
            db.setErrorHandler(new DefaultHandler());
    
            //parse the input file
            Document doc = db.parse(stream);
    
            RegReply reply = new RegReply(doc);
            reply.print(System.out);
    }
  2. Implementar la clase RegReply.

    Observe que el método retrieveValues recorre el árbol DOM del documento XML y extrae el código y el mensaje de estado. La documentación de JAXP ubicada en http://java.sun.com/xml/jaxp/index.html contiene más información.

    class RegReply
    {
            public RegReply(Document doc)
            {
                    retrieveValues(doc);
            }
    
            public String getStatusCode()
            {
                    return (statusCode);
            }
    
            public String getStatusMsg()
            {
                    return (statusMsg);
            }
            public void print(PrintStream out)
            {
                    out.println(statusCode + ": " +
                        (statusMsg != null ? statusMsg : ""));
            }
    
            private void retrieveValues(Document doc)
            {
                    Node n;
                    NodeList nl;
                    String nodeName;
    
                    // Find the SC_REPLY element.
                    nl = doc.getElementsByTagName("SC_REPLY");
                    if (nl.getLength() != 1) {
                            System.out.println("Error in parsing: can't find "
                                + "SC_REPLY node.");
                            return;
                    }
    
                    n = nl.item(0);
    
                    // Retrieve the value of the statusCode attribute
                    statusCode = ((Element)n).getAttribute("STATUS_CODE");
    
                    // Find the SC_STATUS_MSG element
                    nl = ((Element)n).getElementsByTagName("SC_STATUS_MSG");
                    if (nl.getLength() != 1) {
                            System.out.println("Error in parsing: can't find "
                                + "SC_STATUS_MSG node.");
                            return;
                    }
                    // Get the TEXT section, if there is one.
                    n = nl.item(0).getFirstChild();
                    if (n == null || n.getNodeType() != Node.TEXT_NODE) {
                    // Not an error if there isn't one, so we just silently return.
                            return;
                    }
    
                    // Retrieve the value
                    statusMsg = n.getNodeValue();
            }
    
            private String statusCode;
            private String statusMsg;
    }

ProcedureCómo analizar los eventos de rellamada

El paso final consiste en analizar y procesar los eventos reales de rellamada. Para ayudarle en esta tarea, debe modificar la clase Event creada en Cómo generar XML para que esta clase pueda construir un evento, Event, a partir de un documento de XML y crear un elemento, Element, XML: Este cambio requiere un constructor adicional (que incluya un documento de XML), un método retrieveValues, la adición de dos variables de miembros (vendor y publisher), métodos de acceso para todos los campos y, por último, un método de impresión.

Pasos
  1. Crear el código Java que aplica la lógica anterior.

    Tenga en cuenta que este código es similar al de la clase RegReply , que se describe en Cómo analizar el mensaje de respuesta de registro.

    public Event(Document doc)
            {
                    nvpairs = new Vector();
                    retrieveValues(doc);
            }
            public void print(PrintStream out)
            {
                    out.println("\tCLASS=" + regClass);
                    out.println("\tSUBCLASS=" + regSubclass);
                    out.println("\tVENDOR=" + vendor);
                    out.println("\tPUBLISHER=" + publisher);
                    for (int i = 0; i < nvpairs.size(); i++) {
                            NVPair tempNv = (NVPair)
                                (nvpairs.elementAt(i));
                            out.print("\t\t");
                            tempNv.print(out);
                    }
            }
    
            private void retrieveValues(Document doc)
            {
                    Node n;
                    NodeList nl;
                    String nodeName;
    
                    // Find the SC_EVENT element.
                    nl = doc.getElementsByTagName("SC_EVENT");
                    if (nl.getLength() != 1) {
                       System.out.println("Error in parsing: can't find "
                           + "SC_EVENT node.");
                       return;
                    }
    
                    n = nl.item(0);
    
                    //
                    // Retrieve the values of the CLASS, SUBCLASS,
                    // VENDOR and PUBLISHER attributes.
                    //
                    regClass = ((Element)n).getAttribute("CLASS");
                    regSubclass = ((Element)n).getAttribute("SUBCLASS");
                    publisher = ((Element)n).getAttribute("PUBLISHER");
                    vendor = ((Element)n).getAttribute("VENDOR");
    
                    // Retrieve all the nv pairs
                    for (Node child = n.getFirstChild(); child != null;
                        child = child.getNextSibling())
                    {
                           nvpairs.add(new NVPair((Element)child));
                    }
            }
    
            public String getRegClass()
            {
                    return (regClass);
            }
    
            public String getSubclass()
            {
                    return (regSubclass);
            }
    
            public String getVendor()
            {
                    return (vendor);
            }
    
            public String getPublisher()
            {
                    return (publisher);
            }
    
            public Vector getNvpairs()
            {
                    return (nvpairs);
            }
    
            private String vendor, publisher;
  2. Implemente los constructores y métodos adicionales de la clase NVPair compatibles con el análisis XML.

    Los cambios realizados en Event mostrados en el Paso 1 deben también realizarse en la clase NVPair.

    public NVPair(Element elem)
            {
                    retrieveValues(elem);
            }
            public void print(PrintStream out)
            {
                    out.println("NAME=" + name + " VALUE=" + value);
            }
            private void retrieveValues(Element elem)
            {
                    Node n;
                    NodeList nl;
                    String nodeName;
    
                    // Find the NAME element
                    nl = elem.getElementsByTagName("NAME");
                    if (nl.getLength() != 1) {
                       System.out.println("Error in parsing: can't find "
                           + "NAME node.");
                       return;
                    }
                    // Get the TEXT section
                    n = nl.item(0).getFirstChild();
                    if (n == null || n.getNodeType() != Node.TEXT_NODE) {
                       System.out.println("Error in parsing: can't find "
                           + "TEXT section.");
                       return;
                    }
    
                    // Retrieve the value
                    name = n.getNodeValue();
    
                    // Now get the value element
                    nl = elem.getElementsByTagName("VALUE");
                    if (nl.getLength() != 1) {
                       System.out.println("Error in parsing: can't find "
                           + "VALUE node.");
                       return;
                    }
                    // Get the TEXT section
                    n = nl.item(0).getFirstChild();
                    if (n == null || n.getNodeType() != Node.TEXT_NODE) {
                    System.out.println("Error in parsing: can't find "
                                + "TEXT section.");
                            return;
                    }
    
                    // Retrieve the value
                    value = n.getNodeValue();
                    }
    
            public String getName()
            {
                    return (name);
            }
    
            public String getValue()
            {
                    return (value);
            }
    }
  3. Implemente el bucle while en EventReceptionThread, que espera las rellamadas de eventos.

    EventReceptionThread se describe en Cómo definir el subproceso de recepción de eventos.

    while(true) {
                    Socket sock = listeningSock.accept();
                    Document doc = db.parse(sock.getInputStream());
                    Event event = new Event(doc);
                    client.processEvent(event);
                    sock.close();
            }

ProcedureCómo ejecutar la aplicación

Pasos
  1. Conviértase en superusuario o asuma una función similar.

  2. Ejecutar la aplicación.


    # java CrnpClient crnpHost crnpPort localPort ...
    

    El código completo de la aplicación CrnpClient se muestra en Apéndice G, Aplicación CrnpClient.java .