package elte.java2_utikalauz5.io; import java.io.*; import java.nio.*; import java.nio.charset.*; import java.nio.channels.*; import java.util.*; import java.net.*; /** Hálózati szelektíven várakozó egyszálú tesztszerver. @link.forrásfájl {@docRoot}/../data/io/src TesztSzerver2.java @link.letöltés {@docRoot}/../data/io TesztSzerver2.jar @since Java 2 Útikalauz programozóknak 5.0 */ public class TesztSzerver2 { public static void main( String[] args ) throws IOException { final Selector multiplexer = Selector.open(); try { ServerSocketChannel kapcsolódásiCsatorna = null; try { kapcsolódásiCsatorna = kapcsolódásiCsatornátLétrehoz(9999); kapcsolódásiCsatorna.register( multiplexer, SelectionKey.OP_ACCEPT ); leállítóSzálatElindít(multiplexer); System.out.println("Kliensek kiszolgálása. Leállítás: "); klienseketKiszolgál(multiplexer); System.out.println("Leállítás..."); } finally { if( kapcsolódásiCsatorna != null ){ kapcsolódásiCsatorna.close(); } } } finally { multiplexer.close(); } } private static ServerSocketChannel kapcsolódásiCsatornátLétrehoz( int port ) throws IOException { final ServerSocketChannel kapcsolódásiCsatorna = ServerSocketChannel.open(); kapcsolódásiCsatorna.configureBlocking(false); final InetSocketAddress address = new InetSocketAddress("localhost", port); kapcsolódásiCsatorna.socket().bind(address); return kapcsolódásiCsatorna; } private static volatile boolean legyenVége = false; private static void leállítóSzálatElindít( final Selector multiplexer ){ assert multiplexer != null; Thread leállítóSzál = new Thread(){ public void run(){ try { System.in.read(); } catch( IOException e ){} legyenVége = true; multiplexer.wakeup(); } }; leállítóSzál.setDaemon(true); leállítóSzál.start(); } private static class KliensKezelő { final ByteBuffer buffer = ByteBuffer.allocate(1024); private final ByteBuffer outBuffer = ByteBuffer.allocate(1024); private int hossz = 0; private final SocketChannel csatorna; KliensKezelő( SocketChannel csatorna ){ this.csatorna = csatorna; } void válaszol() throws IOException { while (true) { if (hossz<=0 && buffer.position()>=2) { buffer.flip(); hossz=buffer.getShort(0)+2; buffer.compact(); } if (hossz>0 && buffer.position()>=hossz) { buffer.flip(); byte[] bb = new byte[hossz]; hossz = 0; buffer.get(bb); buffer.compact(); DataInputStream dis = new DataInputStream(new ByteArrayInputStream(bb)); String kérés = dis.readUTF(); dis.close(); String válasz = válasz(kérés); ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream dos = new DataOutputStream(baos); dos.writeUTF(válasz); bb = baos.toByteArray(); dos.close(); outBuffer.clear(); outBuffer.put(bb); outBuffer.flip(); csatorna.write(outBuffer); } if ((hossz <=0 && buffer.position()<2) || (hossz>0 && buffer.position() kliensek = new HashMap(); try { while( !legyenVége ){ multiplexer.select(); if( !legyenVége ){ Set kulcsok = multiplexer.selectedKeys(); for( SelectionKey kulcs: kulcsok ){ SelectableChannel csatorna = kulcs.channel(); if( csatorna instanceof ServerSocketChannel ){ kapcsolatotLétrehoz((ServerSocketChannel)csatorna,multiplexer, kliensek ); } else if ( csatorna instanceof SocketChannel ){ klienstKiszolgál( (SocketChannel)csatorna, kulcs, kliensek ); } else { assert false; } } kulcsok.clear(); } } } finally { klienseketLezár(multiplexer); } } private static void kapcsolatotLétrehoz(ServerSocketChannel kapcsolódás, Selector multiplexer, Map kliensek) { assert kapcsolódás.keyFor(multiplexer).isAcceptable(); SocketChannel kapcsolat = null; try { kapcsolat = kapcsolódás.accept(); assert kapcsolat != null; kapcsolat.configureBlocking(false); kapcsolat.register(multiplexer,SelectionKey.OP_READ); kliensek.put( kapcsolat, new KliensKezelő(kapcsolat) ); } catch( IOException e ){ hibaüzenet("Hiba kapcsolat fogadásakor",e); if( kapcsolat != null ){ csatornátLezár(kapcsolat, null); } } } private static void klienstKiszolgál(SocketChannel kapcsolat, SelectionKey kulcs, Map kliensek) { assert kapcsolat.equals(kulcs.channel()) && kulcs.isReadable() && kliensek.containsKey(kapcsolat); KliensKezelő kliensKezelő = kliensek.get(kapcsolat); try { if( kapcsolat.read(kliensKezelő.buffer) == -1 ){ kliensek.remove(kapcsolat); csatornátLezár(kapcsolat,kulcs); } else kliensKezelő.válaszol(); } catch( IOException e ){ hibaüzenet("Hiba a klienskommunikáció alatt",e); csatornátLezár(kapcsolat,kulcs); } } private static void klienseketLezár( Selector multiplexer ){ assert multiplexer != null; for( SelectionKey kulcs: multiplexer.keys() ){ SelectableChannel csatorna = kulcs.channel(); if( csatorna instanceof SocketChannel ) csatornátLezár((SocketChannel)csatorna, kulcs); } } private static void csatornátLezár(SocketChannel kapcsolat, SelectionKey kulcs){ assert (kapcsolat!=null) && (kulcs==null||kulcs.channel().equals(kapcsolat)); try { if( kulcs != null ) kulcs.cancel(); kapcsolat.close(); } catch( IOException e ) { hibaüzenet("Hiba a kapcsolat lezárásakor",e); } } private static void hibaüzenet( String üzenet, Throwable kivétel ){ if( üzenet != null ){ System.err.println(üzenet); } if( kivétel != null ){ kivétel.printStackTrace(); } } }