iHarder.net

Simple Servers

Support This Project

Download

Download now! (v0.1 beta - 151KB)

Follow the file release RSS feed...

Description

The files UdpServer.java, TcpServer.java, and NioServer.java contain Public Domain classes to help embedding network servers in your code. They are thread-safe and robust and well-suited to either GUI or command line applications.

Why

Why provide server code when it's so easy (and fun!) for anyone to write their own in Java? I got tired of always rewriting little UDP and TCP servers for this project or that. Inevitably I'd start with the ol' 10-lines-or-less version, which works great in Java, but then I'd want to be able to change the listening port on the fly or join a multicast group, and I'd have to change my code because it wasn't robust enough in 10 lines. Finally I threw in the towel and wrote good ones to use over and over.

Usage

You can copy just the file you need into your project in whatever package you're using. If you want to try compiling the files on the command line to play with the examples, go to the src directory, and type javac *.java

Here is an example of an Echo program that echoes UDP packets to the console as well as echoing the packets back to the sender:

public class UdpEchoExample {

    public static void main(String[] args) throws Exception{

        int port = 1234;
        try{ port = Integer.parseInt(args[0]); }
        catch( Exception exc ){
            System.out.println("No port, or bad port, provided. Will use " + port );
        }   // end catch

        UdpServer us = new UdpServer();                             // Create the server
        us.setPort( port );                                         // Set the port
        us.addUdpServerListener( new UdpServer.Listener() {         // Add listener
            @Override
            public void packetReceived( UdpServer.Event evt ) {     // Packet received
                System.out.println( evt.getPacketAsString() );      // Write to console
                try {
                    evt.send( evt.getPacket() );                    // Packet magically already contains
                                                                    // return address information
                } catch( java.io.IOException ex ) {
                    ex.printStackTrace(); // Please don't use printStackTrace in production code
                }   // end ctach
            }   // end packetReceived
        }); // end Listener
        us.start();
        System.out.println("Server started on port " + port );

    }   // end main

}   // end class UdpEchoExample

Here is another Echo program, this time with TCP:

public class TcpEchoExample {

    public static void main(String[] args) throws Exception{

        int port = 1234;
        try{ port = Integer.parseInt(args[0]); }
        catch( Exception exc ){
            System.out.println("No port, or bad port, provided. Will use " + port );
        }   // end catch

        TcpServer ts = new TcpServer();                                     // Create the server
        ts.setPort( port );                                                 // Set the port
        ts.addTcpServerListener( new TcpServer.Listener() {                 // Add listener

            @Override
            public void socketReceived( TcpServer.Event evt ) {             // New stream
                try {
                    InputStream in = evt.getSocket().getInputStream();      // Input
                    OutputStream out = evt.getSocket().getOutputStream();   // Output
                    byte[] buff = new byte[64];                             // Buffer
                    int num = -1;                                           // Bytes read
                    while( (num = in.read(buff)) >= 0 ){                    // Not EOS yet
                        System.out.print(new String(buff,0,num) );          // Echo to console
                        out.write( buff, 0, num );                          // Echo to source
                        out.flush();                                        // Flush stream
                    }   // end while
                } catch( IOException exc ) {
                    exc.printStackTrace();
                } finally {
                    try {
                        evt.getSocket().close();
                    } catch( IOException exc2 ) {
                        exc2.printStackTrace();
                    }
                }
            }   // end socketReceived
        }); // end Listener
        ts.start();
        System.out.println("Server started on port " + port );

    }   // end main

}   // end class TcpEchoExample

Finally if you're curious about the java.nio package, the so-called New IO (not so new anymore), you can use the NioServer class such as in this echo example:

public class NioEchoExample {


    public static void main(String[] args) throws Exception{

        if( args.length == 0 ){
            System.out.println("\nNo ports provided. Using port 1234 as default.");
            args = new String[]{ "1234" };
        }

        // Parse command line port requests
        NioServer ns = new NioServer();                                 // New server
        for( String s : args ){
            try{
                int port = Integer.parseInt(args[0]);
                SocketAddress addr = new InetSocketAddress(port);
                ns.addTcpBinding(addr).addUdpBinding(addr);             // Bind to TCP and UDP
                System.out.println("  Listening on port " + port );
            } catch( Exception exc ){
                System.out.println("To specify a port, include it as the first argument.");
            }
        }   // end for
        

        ns.addNioServerListener(new NioServer.Adapter() {               // Listener
            Charset charset = Charset.forName( "US-ASCII" );            // Only print ASCII text
            
            /**
             * Echo all TCP data as it is received.
             */
            @Override
            public void tcpDataReceived(NioServer.Event evt) {
                ByteBuffer inBuff = evt.getInputBuffer();               // Input buffer

                inBuff.mark();                                          // Remember where we started
                System.out.print( charset.decode( inBuff ) );           // Echo to console
                inBuff.reset();                                         // Back to the mark

                ByteBuffer outBuff = evt.getOutputBuffer();             // Output buffer
                outBuff.clear();                                        // Clear output
                outBuff.put( inBuff );                                  // Copy input into output
                outBuff.flip();                                         // Prepare output for playback
            }

            /**
             * Echo all UDP data as it is received.
             */
            @Override
            public void udpDataReceived(NioServer.Event evt) {          // Same as TCP method!
                ByteBuffer inBuff = evt.getInputBuffer();               // Input buffer

                inBuff.mark();                                          // Remember where we started
                System.out.print( charset.decode( inBuff ) );           // Echo to console
                inBuff.reset();                                         // Back to the mark

                ByteBuffer outBuff = evt.getOutputBuffer();             // Output buffer
                outBuff.clear();                                        // Clear output
                outBuff.put( inBuff );                                  // Copy input into output
                outBuff.flip();                                         // Prepare output for playback
            }
        });

        ns.start();
    }   // end main
    
}   // end NioEchoExample

API

I've done my best to thoroughly document the code, if you care to look at the source, or simply view the javadoc-generated API.

Licensing

This code is released into the Public Domain. Enjoy.

Changes

A Note About Public Domain

I have released this software into the Public Domain. That means you can do whatever you want with it. Really. You don't have to match it up with any other open source license &em; just use it. You can rename the files, move the Java packages, whatever you want. If your lawyers say you have to have a license, contact me, and I'll make a special release to you under whatever reasonable license you desire: MIT, BSD, GPL, whatever.


blog comments powered by Disqus