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.