最近很无聊,找些新玩意玩玩,正好看到了mina的介绍,下了2.0M5的zip,看看example,再查查资料,写了下面的列子,虽然简单,但是问题还真不少,好在快下班的时候搞定了,留个纪念,有空再扩展.
看名字就知道是啥,看人家的命名,真不是盖得.
唯一一点要注意的就是session在关闭时的参数,如果有数据没有flush,可能就是报错.如果有多个地方同时关闭,可能会死锁...
package com.hcycom.lan;
import java.net.InetSocketAddress;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
public class ServerHandler extends IoHandlerAdapter {
@Override
public void exceptionCaught(IoSession session, Throwable cause)
throws Exception {
cause.printStackTrace();
session.close(false);
}
@Override
public void messageReceived(IoSession session, Object message)
throws Exception {
String s = message.toString();
System.out.println("收到请求:" + s);
if (s != null) {
int i = getPoint(s);
if (session.isConnected()) {
if (i >= 95) {
session.write("运气不错,你可以出去了.");
session.close(false);
return;
}
Integer count = (Integer) session.getAttribute(Server.KEY);
count++;
session.setAttribute(Server.KEY, count);
session.write("抱歉,你运气太差了,第" + count + "次请求未被通过,继续在小黑屋里呆着吧.");
} else {
session.close(true);
}
}
}
@Override
public void messageSent(IoSession session, Object message) throws Exception {
System.out.println("发给客户端: " + message.toString());
}
@Override
public void sessionClosed(IoSession session) throws Exception {
long l = session.getCreationTime();
System.out.println("来自" + getInfo(session) + "的会话已经关闭,它已经存活了 "
+ (System.currentTimeMillis() - l) + "毫秒.");
}
@Override
public void sessionCreated(IoSession session) throws Exception {
System.out.println("给" + getInfo(session) + "创建了一个新会话.");
}
@Override
public void sessionIdle(IoSession session, IdleStatus status)
throws Exception {
System.out.println("来自" + getInfo(session) + "的会话在闲置,状态为"
+ status.toString());
}
@Override
public void sessionOpened(IoSession session) throws Exception {
session.setAttribute(Server.KEY, 0);
System.out.println("和" + getInfo(session) + "的会话已经打开.");
}
public String getInfo(IoSession session) {
if (session == null) {
return null;
}
InetSocketAddress address = (InetSocketAddress) session
.getRemoteAddress();
int port = address.getPort();
String ip = address.getAddress().getHostAddress();
return ip + ":" + port;
}
public int getPoint(String s) {
if (s == null) {
return -1;
}
Pattern p = Pattern.compile("^[\u0041-\uFFFF,]*(\\d+).*$");
Matcher m = p.matcher(s);
if (m.matches()) {
return Integer.valueOf(m.group(1));
}
return 0;
}
}
客户端,直接继承了HandlerAdapter,不需要写啥太复杂的东西
package com.hcycom.lan;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.Random;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.future.IoFutureListener;
import org.apache.mina.core.service.IoConnector;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
public class Client extends IoHandlerAdapter {
private Random random = new Random(System.currentTimeMillis());
public Client() {
IoConnector connector = new NioSocketConnector();
connector.getFilterChain().addLast(
"text",
new ProtocolCodecFilter(new TextLineCodecFactory(Charset
.forName(Server.ENCODE))));
connector.setHandler(this);
ConnectFuture future = connector.connect(new InetSocketAddress(
"127.0.0.1", Server.PORT));
future.awaitUninterruptibly();
future.addListener(new IoFutureListener<ConnectFuture>() {
@Override
public void operationComplete(ConnectFuture future) {
IoSession session = future.getSession();
while (!session.isClosing()) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
String message = "你好,我roll了" + random.nextInt(100) + "点.";
session.write(message);
}
}
});
connector.dispose();
}
@Override
public void messageReceived(IoSession session, Object message)
throws Exception {
System.out.println("批复:" + message.toString());
}
@Override
public void messageSent(IoSession session, Object message) throws Exception {
System.out.println("报告:" + message.toString());
}
@Override
public void exceptionCaught(IoSession session, Throwable cause)
throws Exception {
cause.printStackTrace();
session.close(true);
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Client();
}
}
}
server端,更简单,就是要注意filter,客户端要和服务器端一致,这里用的是传字符串的,mina实现了很多filter,包括传对象的,有空再玩.
package com.hcycom.lan;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.SocketAcceptor;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
public class Server {
public static final int PORT = 2534;
public static final String ENCODE = "UTF-8";
public static final String KEY = "roll";
public static void main(String[] args) {
SocketAcceptor acceptor = new NioSocketAcceptor();
acceptor.getFilterChain().addLast(
"text",
new ProtocolCodecFilter(new TextLineCodecFactory(Charset
.forName(ENCODE))));
acceptor.setHandler(new ServerHandler());
try {
acceptor.bind(new InetSocketAddress(PORT));
System.out.println("游戏开始,你想出去吗,来,碰碰运气吧!");
} catch (IOException e) {
e.printStackTrace();
acceptor.dispose();
}
}
}