Problem mit Nonblocking Sockets. Nach Verbindunsabbruch kommen Events vom Client

danielm

Erfahrenes Mitglied
Ich spiele gerade mit den Nonblocking Sockets aus dem java.nio Package rum.

Ich hab mir einen Server gebastelt der Verbindungsanfragen von Clients entgegen nimmt und anschließend einfach nur den gesendeten Text der Clients ausgeben soll.
Das funktioniert auch wunderbar, aber sobald ich den Client (In diesem Fall Telnet) beende kommen trotzdem noch weitere read-events vom Client rein. Vll. hab ich das Konzept noch nicht richtig verstanden und jemand kann mir nen kleinen Tipp geben was da los ist ;)

Das ist der entsprechende Code der die Events annimmt und sie an die Client-Objekte weiter gibt...

Java:
	public NIOMediaServer(int port) throws IOException {
		this.setServer(ServerSocketChannel.open());
		
		this.getServer().configureBlocking(false);

		this.getServer().socket().bind(new java.net.InetSocketAddress(InetAddress.getLocalHost(),port));

		this.setSelector(Selector.open());
		
		this.getServer().register(selector,SelectionKey.OP_ACCEPT);
		
		this.start();
	}
	
	public void run() {
		while(!this.isStop()) {
			//Auf events warten
			try {
				this.getSelector().select();
				Set keys = this.getSelector().selectedKeys();
				Iterator i = keys.iterator();
								
				while(i.hasNext()) {
					SelectionKey key = (SelectionKey)i.next();
					
					i.remove();
					
					if(key.isAcceptable()) {
						//Ein Client versucht sich zu verbinden
						SocketChannel client = this.getServer().accept();
						
						//Neuen Client in der HashMap anlegen
						this.getConnectedClients().put(client.hashCode(), new NIOClient(client, this.getSelector()));
					} else if(key.isReadable()) {
						//Ein Client will etwas senden
						
						//Read-Methode des entsprechenden Clients aufrufen
						this.getConnectedClients().get( key.channel().hashCode() ).read();
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

Und so werden sie in den Client-Objekten verarbeitet

Java:
	public NIOClient(SocketChannel channel, Selector selector) {
		this.setBuffer(ByteBuffer.allocate(BUFFER_SIZE));
		this.setState(ClientState.Ready);
		this.setChannel(channel);
		
		try {
			this.getChannel().configureBlocking(false);
			this.getChannel().register(selector, SelectionKey.OP_READ);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	public void read() throws IOException {
	    this.getChannel().read(this.getBuffer());
		
	    this.getBuffer().flip();
	    Charset charset=Charset.forName("ISO-8859-1");
	    CharsetDecoder decoder = charset.newDecoder();
	    CharBuffer charBuffer = decoder.decode(this.getBuffer());	    		
	    
		if(this.getState() == ClientState.Ready) {
			System.out.println("From Client:" + charBuffer.toString());
		}
		
		this.getBuffer().clear();
	}

Wenn ich jetzt etwas vom Client zum Server sende sieht das alles so aus

From Client:hallo du da

From Client:blabla

[--------Jetzt schließe ich Telnet----------]

From Client:
From Client:
From Client:
From Client:
From Client:
From Client:
From Client:
From Client:
From Client:
From Client:
From Client:
From Client:
From Client:
usw.
 
Hallo,

schau mal hier:
Java:
/**
 * 
 */
package de.tutorials;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

/**
 * @author Thomas.Darimont
 * 
 */
public class NIOServerExample {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.socket().bind(
                new InetSocketAddress("localhost", 8888));

        Selector selector = Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        ByteBuffer byteBuffer = ByteBuffer.allocate(1);

        while (true) {
            selector.select();
            Iterator<SelectionKey> selectionKeys = selector.selectedKeys()
                    .iterator();
            while (selectionKeys.hasNext()) {

                SelectionKey selectionKey = selectionKeys.next();
                selectionKeys.remove();

                if (selectionKey.isAcceptable()) {
                    SocketChannel clientSocketChannel = serverSocketChannel
                            .accept();

                    if (clientSocketChannel != null) {

                        System.out.println("Connected: "
                                + clientSocketChannel.hashCode() 
                                + " "
                                + clientSocketChannel);
                        clientSocketChannel.configureBlocking(false);
                        clientSocketChannel.register(selector,
                                SelectionKey.OP_READ);
                    }

                } else if (selectionKey.isReadable()) {

                    SocketChannel clientSocketChannel = (SocketChannel) selectionKey
                            .channel();
                    int bytesRead = clientSocketChannel.read(byteBuffer);
                    if (bytesRead == -1) {
                        selectionKey.cancel();
                        selectionKey.attach(null);
                        clientSocketChannel.close();

                        System.out.println("Disconnected: "
                                + clientSocketChannel.hashCode() 
                                );
                        continue;
                    }
                    byteBuffer.flip();
                    System.out.print((char) byteBuffer.get());
                    byteBuffer.clear();
                }
            }
        }
    }
}

Gruß Tom
 
Zurück