要求就是可以控制某个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<String, IoSession> sessions_ip = new HashMap<String, IoSession>(); // 控制某个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...
客户端不打印。
可以看到本地一个连接连接上去以后,就会开始拒绝新的连接了。至于连接总数的控制,我的注释里面有解释,代码也有这个功能,可以参考下。
Java小强
未曾清贫难成人,不经打击老天真。
自古英雄出炼狱,从来富贵入凡尘。
发表评论: