要求就是可以控制某个IP只能连接一次客户端,或连接的总数量不能超过设定的值。这里使用了apache-mina-2.0.7版本,请注意。
其实这个可以参考官方的一个聊天示例,来一个客户端的时候就缓存下来,走的时候移除。
这里就稍作改造,这里会有一个缓存客户端session的Map,还有一个连接总数的计数器,设定一个IP只能连接一个客户端,然后连接总数不能超过2个。示例中客户端会连接三个连接,休眠后中断连接。
服务端代码:package com.test;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.transport.socket.SocketSessionConfig;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
public class TcpServer extends IoHandlerAdapter {
public static final int PORT = 18567;
private static Map sessions_ip = new HashMap(); // 控制某个IP的连接
private static int sessionSize = 0; // 控制连接总量
@Override
public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
cause.printStackTrace();
session.close(true);
}
@Override
public void messageReceived(IoSession session, Object message) throws Exception {
}
@Override
public void sessionClosed(IoSession session) throws Exception {
InetSocketAddress inetSocketAddress = (InetSocketAddress)session.getRemoteAddress();
InetAddress address = inetSocketAddress.getAddress();
String ip = address.getHostAddress();
int port = inetSocketAddress.getPort();
// 这里是有这个IP才能移除且总数减一,如果你不想以IP来控制,只是要控制总数,那么在客户端来的时候就要以(IP+端口)为依据来缓存该客户端,然后做出减一操作
if(null != sessions_ip.get(ip)) {
System.out.println("客户端离开:" + ip + ":" + port);
sessions_ip.remove(ip + ":" + port);
sessionSize--;
}
System.out.println("Session closed...");
}
@Override
public void sessionCreated(IoSession session) throws Exception {
System.out.println("Session created...");
}
@Override
public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
System.out.println("Session idle...");
}
@Override
public void sessionOpened(IoSession session) throws Exception {
if(sessionSize > 2){
System.err.println("客户端超出最大数量");
session.close(true);
return;
}
InetSocketAddress inetSocketAddress = (InetSocketAddress)session.getRemoteAddress();
InetAddress address = inetSocketAddress.getAddress();
String ip = address.getHostAddress();
int port = inetSocketAddress.getPort();
if(null != sessions_ip.get(ip)) {
System.err.println("该IP已有客户端连接,禁止新链接");
session.close(true);
return;
}
System.out.println("新增客户端:" + ip + ":" + port);
sessions_ip.put(ip, session);
sessionSize++;
System.out.println("Session Opened...");
}
public TcpServer() throws IOException {
NioSocketAcceptor acceptor = new NioSocketAcceptor();
acceptor.setHandler(this);
SocketSessionConfig scfg = acceptor.getSessionConfig();
acceptor.bind(new InetSocketAddress(PORT));
System.out.println("Server started...");
}
public static void main(String[] args) throws IOException {
new TcpServer();
}
}
客户端代码:package com.test;
import java.net.InetSocketAddress;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoConnector;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.transport.socket.SocketSessionConfig;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
public class TcpClient extends IoHandlerAdapter {
private IoConnector connector;
private static IoSession session;
public TcpClient() {
connector = new NioSocketConnector();
connector.setHandler(this);
SocketSessionConfig dcfg = (SocketSessionConfig) connector.getSessionConfig();
ConnectFuture connFuture = connector.connect(new InetSocketAddress("localhost", TcpServer.PORT));
connFuture.awaitUninterruptibly();
session = connFuture.getSession();
}
@Override
public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
cause.printStackTrace();
}
@Override
public void messageReceived(IoSession session, Object message) throws Exception {
}
@Override
public void messageSent(IoSession session, Object message) throws Exception {
}
@Override
public void sessionClosed(IoSession session) throws Exception {
}
@Override
public void sessionCreated(IoSession session) throws Exception {
}
@Override
public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
}
@Override
public void sessionOpened(IoSession session) throws Exception {
}
public static void main(String[] args) throws Exception {
TcpClient client1 = new TcpClient();
TcpClient client2 = new TcpClient();
TcpClient client3 = new TcpClient();
Thread.sleep(3000);
client1.connector.dispose(true);
client2.connector.dispose(true);
client3.connector.dispose(true);
}
}
看服务端和客户端的打印:SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Server started...
Session created...
新增客户端:127.0.0.1:57246
Session Opened...
该IP已有客户端连接,禁止新链接
Session created...
客户端离开:127.0.0.1:57255
Session closed...
该IP已有客户端连接,禁止新链接
Session created...
客户端离开:127.0.0.1:57264
Session closed...
客户端离开:127.0.0.1:57246
Session closed...
客户端不打印。
可以看到本地一个连接连接上去以后,就会开始拒绝新的连接了。至于连接总数的控制,我的注释里面有解释,代码也有这个功能,可以参考下。
推荐您阅读更多有关于“ 网络编程开源mina连接总数 ”的文章