Frage

Als Teil meines Protokolls möchte ich, dass der Client seine Versionsnummer sendet, wenn eine neue Verbindung hergestellt wird.Ich möchte, dass dies in einem separaten Handler in der Pipeline erledigt wird. Bitte haben Sie also Geduld, da dies eine recht einfache Frage sein mag, ich mir aber nicht sicher bin, wie ich das machen soll.Die andere Sache ist, dass ich dann gerne POJOs über die Verbindung (Pipeline) hin und her senden könnte.Außerdem würde ich gerne einen Authentifizierungshandler hinzufügen.Wie dem auch sei, im Moment erhalte ich irgendeine Fehlermeldung, und ich bin mir ziemlich sicher, dass dies daran liegt, dass die Versionsprüfung nicht ordnungsgemäß von der Pipeline verarbeitet wird.

Grundsätzlich ist der Code, den ich unten habe, so eingerichtet, dass er „Hello World“ sendet, das der Server ausdruckt, nachdem die Version überprüft wurde, wenn die Verbindung hergestellt wurde.Zumindest in der Theorie funktioniert das in der Realität nicht ganz ;)

Derzeit habe ich:

Client.java

public static void main(String[] args)
{
    ...

    // Set up the pipeline factory.
    bootstrap.setPipelineFactory(new ChannelPipelineFactory() 
    {
        @Override
        public ChannelPipeline getPipeline() throws Exception 
        {
            return Channels.pipeline(
                    new ObjectEncoder(),
                    new ObjectDecoder(),
                    new VersionClientHandler(),
                    new BusinessLogicClientHandler());
        }
    });     

    ...

    // The idea is that it will all be request and response. Much like http but with pojo's. 
    ChannelFuture lastWriteFuture = channel.write("Hello world".getBytes());

    if (lastWriteFuture != null) 
    {
        System.out.println("waiting for message to be sent");
           lastWriteFuture.awaitUninterruptibly();
    }

    ...
}

VersionClientHandler.java

public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
{
    ChannelBuffer versionBuffer = ChannelBuffers.buffer(VERSION_STRING_LENGTH);
    versionBuffer.writeBytes("v123.45a".getBytes());
    // If I understand correctly, the next line says use the rest of the stream to do what you need to the next Handler in the pipeline?
    Channels.write(ctx, e.getFuture(), versionBuffer);  
}

BusinessLogicClientHandler.java

Not really doing anything at this point. Should it?

Server.java

public static void main(String[] args)
{
    ...

    public ChannelPipeline getPipeline() throws Exception 
    {
        return Channels.pipeline(
                new ObjectEncoder(),
                new ObjectDecoder(),
                new VersionServerHandler(),
                new BusinessLogicServerHandler());
    }

    ...
}

VersionServerHandler.java

public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) 
{
    ChannelBuffer versionBuffer = ChannelBuffers.buffer(VERSION_NUMBER_MAX_SIZE);
    System.out.println("isReadable - messageReceived: " + versionBuffer.readable()); // returns false???
    // Basically I want to read it and confirm the client and server versions match.
    // And if the match fails either send a message or throw an exception
    // How do I also pass on the stream to the next Handler? 
}

BusinessLogicServerHandler.java

public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) 
{
    e.getMessage();
    byte[] message = (byte[])e.getMessage(); // "Hello World" in byte[] from Client.java
}

Im Grunde möchte ich also, dass die Versionsnummer übergeben und validiert wird, wenn der Kanal als Teil des Kommunikationsprotokolls verbunden wird.Alles geschieht automatisch hinter den Kulissen.Ebenso würde ich den Authentifizierungsmechanismus gerne auf diese Weise übergeben.

Ich habe zwar einen Code gesehen, der in etwa dem ähnelte, was ich mit dem Secure Chat-Beispiel machen wollte, aber ich konnte ihn nicht wirklich verstehen.Für jede Hilfe bei der Einrichtung dieses Codes wären wir sehr dankbar.Ich weiß, dass ich alles in einem riesigen Handler erledigen könnte, aber das ist der Sinn der Pipeline, sie in logisch sinnvolle Einheiten aufzuteilen.

War es hilfreich?

Lösung

Ich habe die Lösung gefunden!!!

Es gab eine Reihe von Problemen.

Auf VersionClientHandler lautet der neue Code:

public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
{
    String verison = "v123.45a";

    ChannelBuffer versionBuffer = ChannelBuffers.buffer(VERSION_STRING_LENGTH);
    versionBuffer.writeBytes(version.getBytes());
    e.getChannel().write(version);
}

Beachten Sie die letzte Zeile: e.getChannel().write(version); anstatt Channels.write(ctx, e.getFuture(), versionBuffer); Ich bin mir nicht sicher, warum. Tatsächlich fange ich gleich an zu untersuchen, warum ich den ChannelBuffers-Code dort habe, weil er scheinbar nichts bewirkt ...

Auf VersionServerHandler.java habe ich jetzt:

public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) 
{
    String versionCheck = (String)e.getMessage();
    System.out.println("VersionServerHandler - " + versionCheck);
    ctx.getPipeline().remove(VersionServerHandler.class);
}

Beachten Sie, dass ich den Puffer nicht mehr durchlese, sondern einfach e.getMessage() und in den richtigen Objekttyp umwandeln.Darüber habe ich hinzugefügt ctx.getPipeline().remove(VersionServerHandler.class); Dies dient dazu, diesen Handler von jeglicher weiteren Verarbeitung zu entfernen.Nach der ersten Verbindung ist es nicht mehr erforderlich.Danke an Dennis für diesen Tipp.

Abschluss

Der Rest entspricht weitgehend meinen Erwartungen.Der Schlüssel liegt darin, dass ich nicht richtig verstanden habe, wie man die Puffer liest und die Informationen weitergibt.Und die Fehlermeldungen und Beispiele waren nicht ganz klar.Sobald Sie die POJO-Kanäle von Netty zu Ihrer Pipeline hinzufügen, müssen Sie für alle Handler nur noch mit Objekten umgehen.Das habe ich verpasst.Die Konzepte waren richtig, nur die Art und Weise, wie ich versucht habe, die Daten aus den Kanälen zu lesen, war falsch.

Der andere große Tipp war, die Handler aus der Pipeline zu entfernen, wenn Sie sie nach der ersten Verbindung nicht benötigen.Ich gehe davon aus, dass das Gleiche auch für einen Authentifizierungshandler gilt.Es wäre toll, hier eine Bestätigung zu haben, aber das muss ich später herausfinden.

Andere Tipps

Sie haben nicht erwähnt, was der Fehler war, den Sie sehen.

Auf jeden Fall würde ich nicht empfehlen, einen separaten Channel-Handler für die Versionsprüfung zu verwenden.Vor allem, weil die Versionsprüfung nur einmal beim ersten Verbindungsaufbau erfolgen sollte.Auch weil ich denke, dass die Channel-Handler sich am besten mit Transportschichtproblemen befassen sollten, z.Konvertieren von Bytes in Pojos.

Ich habe ein einfaches Beispiel erstellt: https://github.com/boldt/netty-examples/

Es gibt die Versionsnummer zurück, wenn eine neue Verbindung hergestellt wird.Dies geschieht in einem separaten Handler, der aus der Pipeline entfernt wird, nachdem die Version auf den Kanal geschrieben wurde.Anschließend handelt es sich um das ECHO-Beispiel aus dem Netty-Tutorial.

A telnet localhost 1234 an den Server zeigt die Version sofort an.

Auf diese Weise könnten Sie der Pipeline hinter dem Versionshandler einen Authentifizierungshandler hinzufügen.

Ich denke, dass das, was Sie tun möchten, leicht archiviert werden kann, indem Sie einige benutzerdefinierte Handler hinzufügen.Für die Versionsprüfung könnten Sie also einen Handler hinzufügen, der „channelConnected(....)“ überschreibt, und die Prüfung dort durchführen.Für die Authentifizierung fügen Sie nach der Versionsprüfung einfach einen weiteren Handler hinzu, der die Methode messageRecieved(....) überschreibt.Nachdem die Authentifizierung abgeschlossen ist, können Sie den Handler aus der Pipeline entfernen und ihn wieder hinzufügen, wenn Sie ihn erneut benötigen.

Der BusinessLogic-Handler sollte als letzter in der Pipeline stehen.Beachten Sie jedoch, dass einer Ihrer Handler einen Blockierungsvorgang ausführt. Sie sollten darüber nachdenken, davor einen ExecutionHandler hinzuzufügen, um sicherzustellen, dass der ioworker-Thread nicht blockiert wird und der Netty-Server somit unverantwortlich wird.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top