FileDocCategorySizeDatePackage
TypeServer.javaAPI DocExample4875Sat Jul 31 20:37:30 BST 2004javathreads.examples.ch12.example3

TypeServer

public class TypeServer extends TCPNIOServer

Fields Summary
static String
testString
Map
allClients
Charset
encoder
Constructors Summary
Methods Summary
protected voidhandleClient(java.nio.channels.SelectionKey key)


          
        SocketChannel sc = (SocketChannel) key.channel();
       ClientInfo ci = (ClientInfo) allClients.get(sc);
        if (ci == null)
            throw new IllegalStateException("Unknown client");
        if (key.isWritable())
            send(sc, ci);
        if (key.isReadable())
            recv(sc, ci);
    
public static voidmain(java.lang.String[] args)

        TypeServer ts = new TypeServer();
        ts.port = Integer.parseInt(args[0]);
        Thread t = new Thread(ts);
        t.start();
        System.out.println("Type server ready...Type CTRL-D to exit");
        while (System.in.read() > 0)
            ;
        ts.stopServer();
        t.join();
    
private voidrecv(java.nio.channels.SocketChannel sc, javathreads.examples.ch12.example3.TypeServer$ClientInfo ci)

        ci.channel.read(ci.inBuf);
        ByteBuffer tmpBuf = ci.inBuf.duplicate();
        tmpBuf.flip();
        int bytesProcessed = 0;
        boolean doneLoop = false;
        while (!doneLoop) {
            byte b;
            try {
                b = tmpBuf.get();
            } catch (BufferUnderflowException bue) {
                // Processed all data in buffer
               ci.inBuf.clear();
                doneLoop = true;
                break;
            }
            switch(b) {
                case TypeServerConstants.WELCOME:
                    bytesProcessed++;
                    break;
                case TypeServerConstants.GET_STRING_REQUEST:
                    bytesProcessed++;
                    if (ci.outputPending) {
                        // Client is backed up. We can't append to
                        // the byte buffer because it's in the wrong
                        // state. We could allocate another buffer
                        // here and change our send method to know
                        // about multiple buffers, but we'll just
                        // assume that the client is dead
                        break;
                    }
                    ci.outBuf.put(TypeServerConstants.GET_STRING_RESPONSE);
                    ByteBuffer strBuf = encoder.encode(testString);
		    ci.outBuf.putShort((short) strBuf.remaining());
                    ci.outBuf.put(strBuf);
                    ci.outBuf.flip();
                    send(sc, ci);
                    break;
                case TypeServerConstants.GET_STRING_RESPONSE:
                    int startPos = tmpBuf.position();
                    try {
                        int nBytes = tmpBuf.getInt();
                        byte[] buf = new byte[nBytes];
                        tmpBuf.get(buf);
                        bytesProcessed += buf.length + 5;
                        String s = new String(buf);
                        // Send the string to the GUI
                        break;
                    } catch (BufferUnderflowException bue) {
                        // Processed all available data
                        ci.inBuf.position(ci.inBuf.position() + bytesProcessed);
                        doneLoop = true;
                    }
                    break;
            }
        }
    
protected voidregisteredClient(java.nio.channels.SocketChannel sc)

        ClientInfo ci = new ClientInfo();
        ci.channel = sc;
        ci.outBuf.clear();
        ci.outBuf.put(TypeServerConstants.WELCOME);
        ci.outBuf.flip();
        allClients.put(sc, ci);
        send(sc, ci);
    
private voidsend(java.nio.channels.SocketChannel sc, javathreads.examples.ch12.example3.TypeServer$ClientInfo ci)

        int len = ci.outBuf.remaining();
        int nBytes = sc.write(ci.outBuf);
        if (nBytes != len) {
            // Client not ready to receive data
            ci.outputPending = true;
            ci.channel.register(selector,
                         SelectionKey.OP_READ|SelectionKey.OP_WRITE);
        }
        else {
            ci.outBuf.clear();
            if (ci.outputPending) {
                ci.outputPending = false;
                ci.channel.register(selector, SelectionKey.OP_READ);
            }
        }