/* * Copyright (c) 2006-2007 Sun Microsystems, Inc. All rights reserved. * * The Sun Project JXTA(TM) Software License * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. The end-user documentation included with the redistribution, if any, must * include the following acknowledgment: "This product includes software * developed by Sun Microsystems, Inc. for JXTA(TM) technology." * Alternately, this acknowledgment may appear in the software itself, if * and wherever such third-party acknowledgments normally appear. * * 4. The names "Sun", "Sun Microsystems, Inc.", "JXTA" and "Project JXTA" must * not be used to endorse or promote products derived from this software * without prior written permission. For written permission, please contact * Project JXTA at http://www.jxta.org. * * 5. Products derived from this software may not be called "JXTA", nor may * "JXTA" appear in their name, without prior written permission of Sun. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SUN * MICROSYSTEMS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * JXTA is a registered trademark of Sun Microsystems, Inc. in the United * States and other countries. * * Please see the license information page at : * <http://www.jxta.org/project/www/license.html> for instructions on use of * the license in source files. * * ==================================================================== * * This software consists of voluntary contributions made by many individuals * on behalf of Project JXTA. For more information on Project JXTA, please see * http://www.jxta.org. * * This license is based on the BSD license adopted by the Apache Foundation. */ package tutorial.bidi; import net.jxta.document.AdvertisementFactory; import net.jxta.endpoint.Message; import net.jxta.endpoint.MessageElement; import net.jxta.endpoint.StringMessageElement; import net.jxta.logging.Logging; import net.jxta.peergroup.PeerGroup; import net.jxta.pipe.PipeID; import net.jxta.pipe.PipeMsgEvent; import net.jxta.pipe.PipeMsgListener; import net.jxta.pipe.PipeService; import net.jxta.platform.NetworkManager; import net.jxta.protocol.PipeAdvertisement; import net.jxta.util.JxtaBiDiPipe; import net.jxta.util.JxtaServerPipe; import java.io.File; import java.io.IOException; import java.net.URI; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import java.util.logging.Logger; /** * This is the server (receiver) side of the Bi-directional Pipe Tutorial. * <p/> * This example does the following : * <ol> * <li>Open a server pipe.</li> * <li>Listen for connect requests via {@code accept()}.</li> * <li>For each connect request spawn a thread which: * <ol> * <li>Sends {@code ITERATIONS} messages to the connection.</li> * <li>Waits {@code ITERATIONS} responses.</li> * </ol></li> * </ol> */ public class JxtaServerPipeExample { /** * Logger. */ private final static transient Logger LOG = Logger.getLogger(JxtaServerPipeExample.class.getName()); /** * Connection count. */ private final static AtomicInteger connection_count = new AtomicInteger(0); /** * Number of messages to send */ final static int ITERATIONS = 1000; final static String MESSAGE_NAMESPACE_NAME = "bidi_tutorial"; final static String MESSAGE_ELEMENT_NAME = "sequence"; final static String RESPONSE_ELEMENT_NAME = "response"; private final static PipeID BIDI_TUTORIAL_PIPEID = PipeID.create(URI.create("urn:jxta:uuid-59616261646162614E504720503250338944BCED387C4A2BBD8E9411B78C284104")); /** * Gets the pipeAdvertisement attribute of the JxtaServerPipeExample class * * @return The pipeAdvertisement */ public static PipeAdvertisement getPipeAdvertisement() { PipeAdvertisement advertisement = (PipeAdvertisement) AdvertisementFactory.newAdvertisement(PipeAdvertisement.getAdvertisementType()); advertisement.setPipeID(BIDI_TUTORIAL_PIPEID); advertisement.setType(PipeService.UnicastType); advertisement.setName("JxtaBiDiPipe tutorial"); return advertisement; } /** * Connection wrapper. Once started, it sends ITERATIONS messages and * receives a response from the initiator for each message. */ private static class ConnectionHandler implements Runnable, PipeMsgListener { private final JxtaBiDiPipe pipe; private final AtomicInteger received_count = new AtomicInteger(0); /** * Constructor for the ConnectionHandler object * * @param pipe message pipe */ ConnectionHandler(JxtaBiDiPipe pipe) { this.pipe = pipe; pipe.setMessageListener(this); } /** * {@inheritDoc} */ public void pipeMsgEvent(PipeMsgEvent event) { synchronized (received_count) { received_count.incrementAndGet(); received_count.notify(); } try { // grab the message from the event Message msg = event.getMessage(); if (Logging.SHOW_FINER && LOG.isLoggable(Level.FINER)) { LOG.finer("[" + Thread.currentThread().getName() + "] Received a response"); } // get the message element named SenderMessage MessageElement msgElement = msg.getMessageElement(MESSAGE_NAMESPACE_NAME, RESPONSE_ELEMENT_NAME); if(null == msgElement) { if (Logging.SHOW_WARNING && LOG.isLoggable(Level.WARNING)) { LOG.log(Level.WARNING, "[" + Thread.currentThread().getName() + "] Missing message element"); } return; } // Get message if (msgElement.toString() == null) { if (Logging.SHOW_WARNING && LOG.isLoggable(Level.WARNING)) { LOG.log(Level.WARNING, "[" + Thread.currentThread().getName() + "] Null message receved"); } return; } // System.out.println("Got Message :" + msgElement.toString()); } catch (Exception e) { if (Logging.SHOW_WARNING && LOG.isLoggable(Level.WARNING)) { LOG.log(Level.WARNING, "[" + Thread.currentThread().getName() + "] Failure during message receipt.", e); } } } /** * Send a series of messages over a pipe * * @param pipe the pipe to send messages over * @throws IOException Thrown for errors sending messages. */ private void sendTestMessages(JxtaBiDiPipe pipe) throws IOException { long start = System.currentTimeMillis(); // Send ITERATIONS messages to the initiator. for (int send_count = 0; send_count < ITERATIONS; send_count++) { Message msg = new Message(); String data = "Seq #" + send_count; msg.addMessageElement(MESSAGE_NAMESPACE_NAME, new StringMessageElement(MESSAGE_ELEMENT_NAME, data, null)); System.out.println("[" + Thread.currentThread().getName() + "] Sending message :" + send_count); pipe.sendMessage(msg); } // Wait for the last responses to arrive. synchronized(received_count) { while(received_count.get() < ITERATIONS) { try { received_count.wait(); } catch(InterruptedException woken) { Thread.interrupted(); if(!pipe.isBound()) { break; } } } } // Compute the message throughput. int transactions = received_count.get(); long finish = System.currentTimeMillis(); long delta = finish - start; double tps = (0 != delta) ? transactions * 1000.0 / delta : transactions * 1000.0; System.out.println("[" + Thread.currentThread().getName() + "] Completed " + transactions + " in " + delta + "ms. (" + tps + "/TPS)."); } /** * Main processing method for the ConnectionHandler object */ public void run() { try { sendTestMessages(pipe); System.out.println("[" + Thread.currentThread().getName() + "] Closing the pipe"); pipe.close(); } catch (Throwable all) { LOG.log(Level.SEVERE, "[" + Thread.currentThread().getName() + "] Failure in ConnectionHandler", all); } } } /** * main * * @param args command line args */ public static void main(String args[]) { try { final File home = new File(new File(".cache"), "server"); NetworkManager manager = new NetworkManager(NetworkManager.ConfigMode.ADHOC, "JxtaServerPipeExample", home.toURI()); manager.startNetwork(); PeerGroup netPeerGroup = manager.getNetPeerGroup(); PipeAdvertisement serverPipeAdv = JxtaServerPipeExample.getPipeAdvertisement(); JxtaServerPipe serverPipe = new JxtaServerPipe(netPeerGroup, serverPipeAdv); // block forever until a connection is accepted serverPipe.setPipeTimeout(0); System.out.println("Waiting for JxtaBidiPipe connections on JxtaServerPipe : " + serverPipeAdv.getPipeID()); while (true) { JxtaBiDiPipe bipipe = serverPipe.accept(); if (bipipe != null) { System.out.println("JxtaBidiPipe accepted from " + bipipe.getRemotePeerAdvertisement().getPeerID() + " : " + bipipe.getRemotePipeAdvertisement().getPipeID() + " sending " + ITERATIONS + " messages."); // Send messages Thread thread = new Thread(new ConnectionHandler(bipipe), "Connection Handler " + connection_count.incrementAndGet()); thread.start(); } } } catch (Throwable all) { LOG.log(Level.SEVERE,"Failure opening server pipe.", all); System.exit(-1); } } }