In Kapitel 1 hatten wir ein allgemeines Verständnis von MINA. In diesem Kapitel werden wir eine detaillierte Analyse des Client/Server-Modells in MINA durchführen. Außerdem werden einige Beispiele basierend auf TCP und UDP bereitgestellt.
Anwendungsstruktur
Serverstruktur
Client-Struktur
Einfacher TCP-Server
Einfacher TCP-Client
Einfacher UDP-Server
Einfacher UDP-Client
Zusammenfassung der Anwendungsstruktur
Die Struktur einer Anwendung, die das MINA-Framework verwendet, ist wie folgt:
Von oben Wie Sie in sehen können In der Abbildung fungiert MINA als mittlere Schicht, um Ihre Anwendung mit der untersten Schicht des Netzwerks zu verbinden. Es kann TCP, UDP und sogar ein serielles Kommunikationsprotokoll (RS-232C) verarbeiten, sodass Sie sich mehr auf die Entwicklung von Anwendungen auf MINA konzentrieren können. Ohne die Komplexität der zugrunde liegenden Netzwerkkommunikation verstehen zu müssen.
Hier ein Blick ins Innere von MINA:
Im Allgemeinen sind MINA-Anwendungen in drei Schichten unterteilt.
E/A-Dienst – echte E/A-Operation
E/A-Filterkette – Daten filtern/übertragen
E/A-Handler – Vervollständigen Sie hier die Logik des Programms
Um eine MINA-Anwendung zu erstellen, müssen Sie also nur Folgendes tun:
I/O-Dienst erstellen – wählen Sie einen bereits bereitgestellten Dienst (Akzeptor) aus oder erstellen Sie Ihren eigenen Dienst
Filterkette erstellen – wählen Sie einen bereits bereitgestellten aus Service-Filterkette oder erstellen Sie Ihre eigene benutzerdefinierte Filterkette
Erstellen Sie I/OHandler – schreiben Sie Geschäftslogik und verarbeiten Sie verschiedene Nachrichten
Werfen wir einen Blick auf die Struktur von Serverseite:
Vereinfacht ausgedrückt gibt es auf der Serverseite einen I/O-Akzeptor, der auf eingehende Verbindungen oder Datenpakete wartet. Es wird eine neue Sitzung erstellt und nachfolgende Anfragen von dieser Verbindung werden in dieser Sitzung verarbeitet. Alle Pakete werden von der Sitzung akzeptiert und durchlaufen die in der Abbildung oben dargestellte Filterkette. Filterketten werden verwendet, um den Inhalt des Pakets zu ändern (z. B. Konvertieren in Objekte, Hinzufügen oder Entfernen einiger Informationen). Abschließend werden diese Pakete vom IOHandler verarbeitet. Beachten Sie außerdem, dass beim Eintreffen einer Verbindung eine Sitzung eingerichtet wird. Unabhängig davon, ob die Verbindung erfolgreich ist oder nicht, wird die Sitzung eingerichtet.
Das Folgende ist das Client-Modell:
Client und Server Es ist genau der entgegengesetzte Zustand.
Der Client verfügt über einen IOConnector, um eine Verbindung zum Server herzustellen. Und die gesamte Verarbeitung wird weiterhin von IOHandler abgeschlossen.
Einfacher TCP-Server
Erstellen Sie als Nächstes einen einfachen TCP-Server zur Demonstration: Zuerst müssen Sie einige erforderliche Pakete in die IDE importieren oder Ihren CLASSPATH konfigurieren. Die spezifische Methode wird nicht detailliert beschrieben . Ja, die erforderlichen Pakete sind:
MINA 2.x Core
JDK 1.5 oder höher
SLF4J 1.3.0 oder höher
Log4J 1.2-Benutzer: slf4j-api.jar , slf4j-log4j12.jar und Log4J 1.2.x
Log4J 1.3-Benutzer: slf4j-api.jar, slf4j-log4j13.jar und Log4J 1.3.x
java.util.logging-Benutzer: slf4j-api. jar und slf4j-jdk14.jar
WICHTIG: Bitte stellen Sie sicher, dass Sie das richtige slf4j-*.jar verwenden, das zu Ihrem Protokollierungsframework passt.
Nachdem die Vorbereitungen abgeschlossen sind, beginnen wir mit dem Schreiben von Code
import java.net.InetSocketAddress; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; public class MinaTimeServer { private static final int PORT = 9123; public static void main( String[] args ) throws IOException { IoAcceptor acceptor = new NioSocketAcceptor(); acceptor.bind( new InetSocketAddress(PORT) ); } }
Als nächstes fügen wir die Filterkettenkonfiguration zum obigen Code hinzu.
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.charset.Charset; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.TextLineCodecFactory; import org.apache.mina.filter.logging.LoggingFilter; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; public class MinaTimeServer { public static void main( String[] args ) { IoAcceptor acceptor = new NioSocketAcceptor(); acceptor.getFilterChain().addLast( "logger", new LoggingFilter() ); //这里会建立所有的日志信息 acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" )))); //第二个过滤器用来传递数据 acceptor.bind( new InetSocketAddress(PORT) ); } }
Als nächstes müssen wir den Handler definieren, der zum Verarbeiten von Nachrichten verwendet wird. Diese Handler-Klasse muss die IoHandler-Schnittstelle implementieren. In MINA ist dieser Handler der Schlüssel zur Programmentwicklung. In diesem Tutorial erben wir von IoHandlerAdapter.
import java.util.Date; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; public class TimeServerHandler extends IoHandlerAdapter { @Override public void exceptionCaught( IoSession session, Throwable cause ) throws Exception { cause.printStackTrace(); } @Override public void messageReceived( IoSession session, Object message ) throws Exception { String str = message.toString(); if( str.trim().equalsIgnoreCase("quit") ) { session.close(); return; } Date date = new Date(); session.write( date.toString() ); System.out.println("Message written..."); } @Override public void sessionIdle( IoSession session, IdleStatus status ) throws Exception { System.out.println( "IDLE " + session.getIdleCount( status )); } }
Abschließend lautet der vollständige Servercode wie folgt:
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.charset.Charset; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.TextLineCodecFactory; import org.apache.mina.filter.logging.LoggingFilter; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; public class MinaTimeServer { private static final int PORT = 9123; public static void main( String[] args ) throws IOException { IoAcceptor acceptor = new NioSocketAcceptor(); acceptor.getFilterChain().addLast( "logger", new LoggingFilter() ); acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" )))); acceptor.setHandler( new TimeServerHandler() ); //这里设置Handler acceptor.getSessionConfig().setReadBufferSize( 2048 ); //这是设置ssesion缓冲区 acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 ); acceptor.bind( new InetSocketAddress(PORT) ); } }
Starten Sie den Server, öffnen Sie dann das Terminal und geben Sie den Befehl ein: telnet 127.0.0.1 9123. Sie werden sehen Wenn Sie etwas anderes als „Quit“ eingeben, gibt der Server die aktuelle Uhrzeit an das Terminal zurück.
Einfacher TCP-Client
import java.net.InetSocketAddress; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.session.IoSession; import org.apache.mina.example.sumup.codec.SumUpProtocolCodecFactory; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory; import org.apache.mina.filter.logging.LoggingFilter; import org.apache.mina.transport.socket.nio.NioSocketConnector; /** * (<strong>Entry Point</strong>) Starts SumUp client. * * @author <a href="http://mina.apache.org">Apache MINA Project</a> */ public class Client { private static final String HOSTNAME = "localhost"; private static final int PORT = 8080; private static final long CONNECT_TIMEOUT = 30*1000L; // 30 seconds // Set this to false to use object serialization instead of custom codec. private static final boolean USE_CUSTOM_CODEC = true; public static void main(String[] args) throws Throwable { if (args.length == 0) { System.out.println("Please specify the list of any integers"); return; } // prepare values to sum up int[] values = new int[args.length]; for (int i = 0; i < args.length; i++) { values[i] = Integer.parseInt(args[i]); } NioSocketConnector connector = new NioSocketConnector(); // Configure the service. connector.setConnectTimeoutMillis(CONNECT_TIMEOUT); if (USE_CUSTOM_CODEC) {
connector.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new SumUpProtocolCodecFactory(false))); } else { connector.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new ObjectSerializationCodecFactory())); } connector.getFilterChain().addLast("logger", new LoggingFilter()); connector.setHandler(new ClientSessionHandler(values)); IoSession session; for (;;) { try { ConnectFuture future = connector.connect(new InetSocketAddress( HOSTNAME, PORT)); future.awaitUninterruptibly(); session = future.getSession(); break; } catch (RuntimeIoException e) { System.err.println("Failed to connect."); e.printStackTrace(); Thread.sleep(5000); } } // wait until the summation is done session.getCloseFuture().awaitUninterruptibly(); connector.dispose(); } }
Ich werde das UDP-Beispiel nicht schreiben. Schauen Sie sich bei Bedarf die offizielle Apache-Website an.
http://mina.apache.org/mina-project/userguide/ch2-basics/sample-udp-client.html
Das Obige ist Apache Mina Lernnotizen (2) - Grundlegende Inhalte. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (www.php.cn)!