MINA2-TCP服务端实例
為什么80%的碼農都做不了架構師?>>> ??
本教程將引導創建一個基于MINA的程序實例,例子是一個時間服務器。
編寫MINA時間服務器
以創建一個名為MinaTimeServer.java的源文件開始,初始代碼如下:
public class MinaTimeServer{public static void main(String[] args){// code will go here next} }?這段代碼對于所有人來說應該都是很明了的了,我們簡單的定義了一個main方法用來啟動這個程序,這時,我們就開始添加代碼來構造我們的服務器。第一步,我們需要創建一個對象用來監聽所有接入的連接。因為這個程序是基于TCP/UDP的,我們將添加一個SocketAcceptor在我們的程序中。
import org.apache.mina.transport.socket.nio.NioSocketAcceptor; public class MinaTimeServer{public static void main( String[] args ){IoAcceptor acceptor =new NioSocketAcceptor();} }在類NioSocketAcceptor被創建之后,我們就可以繼續定義一個處理程序類,并將這個NioSocketAcceptor綁定到一個端口上:
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)); ???????????} }?如你所見,這里有一個方法調用acceptor.bind(?new?InetSocketAddress(PORT)?),這個方法定義了這個服務將要監聽的主機和端口,并開始接收傳入的連接。
? ? ? ?接下來,我們添加一個過濾器的配置,這個過濾器將記錄所有的日志信息,如新創建了會話,接收消息,發送消息和會話關閉等。下一個過濾器是協議編解碼過濾器ProtocolCodecFilter,這個過濾器可以將二進制文件或協議特定數據轉換為消息對象,或進行反向轉換。這里,我們使用了一個已存在的文本行轉換工廠,它可以替你處理基于文本的消息轉換(你不需要自己實現這個):
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));} }接下來,我們將定義可同時為來自不同客戶端的請求進行服務的處理程序,處理程序類必須實現IoHandler接口。對于大多數基于MINA程序來說,這是程序的核心部分,它將實際處理所有來自客戶端的請求。在本教程中,我們將通過繼承類IoHandlerAdapter來實現。這個類采用了適配器模式,這極大的簡少了滿足不同需求所需的代碼量,它本身實現了IoHandler接口。
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 )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());acceptor.bind(new InetSocketAddress(PORT)); ???????????} }接下來開始添加一些NioSocketAcceptor的配置,這些配置允許我們對從客戶端接入的socket進行一些特殊設置。
import java.net.InetSocketAddress; import java.nio.charset.Charset; import org.apache.mina.core.session.IdleStatus; 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 )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());acceptor.getSessionConfig().setReadBufferSize(2048);acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE,10);acceptor.bind(new InetSocketAddress(PORT));} }類MinaTimeServer中加入了兩行新的代碼,這些方法用來設置IoHandler的配置,如讀取緩沖器大小和session的空閑時間屬性。設置緩沖器的大小用來告訴底層操作系統在為傳入的數據分配空間時,每次分配的大小。第二行的用來設置多久檢查一次空閑session,其中,第一個參數定義了用什么策略來檢查一個會話是否空閑,第二個參數定義了一個session閑置了多少秒時進行一次檢查。
? ? ? 處理程序的代碼如下:
import java.util.Date;importorg.apache.mina.core.session.IdleStatus; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession;public class TimeServerHandler extends IoHandlerAdapter {@Overridepublic void exceptionCaught( IoSession session, Throwable cause )throws Exception{cause.printStackTrace();}@Overridepublic 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...");}@Overridepublic void sessionIdle( IoSession session, IdleStatus status )throws Exception{System.out.println("IDLE "+ session.getIdleCount( status ));} }?在這個類中使用了的方法有:exceptionCaught,messageReceived和sessionIdle。
? ? ? ?在一個處理程序中,exceptionCaught應該總是被定義為捕捉在正常處理遠程連接時候拋出的異常,如果不定義這個方法,異常發生時可能不會正確的被通知。
? ? ? ?本例中的exceptionCaught方法只是簡單的打印出堆棧跟蹤的錯誤信息并將該session關閉,多數情況下,這是個標準的做法,除非處理程序可以做到從異常中恢復。
? ? ? ?例子中的messageReceived方法將接收客戶端數據進行處理并立刻返回給客戶端數據。如果從客戶端接收到單詞“quit”,則會關閉該session,該方法依然會在客戶端打印出系統當前時間。借助于所使用的協議編碼解碼器,該方法傳遞的對象(方法中的第二個參數Object message)和原來的相比會有所變化,同樣,使用session.write(Object)方法進行傳遞的對象也會是不同的。如果不指定一個協議編解碼器,你接收到的將很有可能是一個IoBuffer對象,同時,你也必須返回一個IoBuffer對象。
sessionIdle方法會在一個session閑置了acceptor.getSessionConfig().setIdleTime(?IdleStatus.BOTH_IDLE,?10?)中定義的時間后被調用。
? ? ? 最后要做的是定義服務器要監聽的socket地址,并通過調用主方法啟動服務器,該代碼如下所示:
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());acceptor.getSessionConfig().setReadBufferSize(2048);acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE,10);acceptor.bind(new InetSocketAddress(PORT)); ???????????} }試用該時間服務器:
這時,我們就可以繼續進行編譯操作,一旦編譯過該程序,就可以執行改程序并測試會發生什么。最簡單的測試該服務器的方法是啟動該程序,并通過telnet測試改程序
| user@myhost:~> telnet 127.0.0.1 9123? Trying 127.0.0.1...? Connected to 127.0.0.1.? Escape character is '^]'.? hello? Wed Oct 17 23:23:36 EDT 2007? quit? Connection closed by foreign host.? user@myhost:~> | MINA Time server started.? Message written... |
轉載于:https://my.oschina.net/shajin/blog/823985
總結
以上是生活随笔為你收集整理的MINA2-TCP服务端实例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: bootstrap模态框使用
- 下一篇: 脑人