Sloppy's Blog

Servlet与Mina框架的Socket进行通信

背景

在游戏业务中,这种需求很常用,游戏大都是Socket通信。而且游戏外接的SDK,外接的平台都是HTTP Servlet供访问访问,或者GM工具都是HTTP协议的形式出现,这就需要Java web服务器的Servlet能跟socket进行游戏,目前我们的游戏中也用到了这种方式,

代码

下载最新的mina包,及相关的依赖包

  • log4j-1.2.17.jar
  • mina-core-2.0.16.jar
  • mina-http-2.0.16.jar
  • slf4j-api-1.7.25.jar
  • slf4j-log4j12-1.7.25.jar

新建java web项目,把上面相应的包,copy进:WebContent/WEB-INF/lib

编写类:ClientHandler,用于处理Mina Socket连接的IOHandler,代码如下:

package com.nikoer.mina;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.mina.core.service.IoHandler;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;

public class ClientHandler implements IoHandler {

    public static final Map results = new ConcurrentHashMap();
    @Override
    public void exceptionCaught(IoSession arg0, Throwable arg1)
            throws Exception {
        // TODO Auto-generated method stub

    }

    @Override
    public void inputClosed(IoSession arg0) throws Exception {
        // TODO Auto-generated method stub

    }

    @Override
    public void messageReceived(IoSession session, Object message) throws Exception {
        // TODO Auto-generated method stub
        String flag = (String)session.getAttribute("SendRequestFlag");
        results.put(flag, message);
        session.closeNow();
    }

    @Override
    public void messageSent(IoSession arg0, Object arg1) throws Exception {
        // TODO Auto-generated method stub

    }

    @Override
    public void sessionClosed(IoSession arg0) throws Exception {
        // TODO Auto-generated method stub

    }

    @Override
    public void sessionCreated(IoSession arg0) throws Exception {
        // TODO Auto-generated method stub

    }

    @Override
    public void sessionIdle(IoSession arg0, IdleStatus arg1) throws Exception {
        // TODO Auto-generated method stub

    }

    @Override
    public void sessionOpened(IoSession arg0) throws Exception {
        // TODO Auto-generated method stub

    }

}

新建 Servlet类:

package com.nikoer.mina;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.service.IoConnector;
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;

/**
 * Servlet implementation class HelloMinaServlet
 */
@WebServlet("/HelloMinaServlet")
public class HelloMinaServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public HelloMinaServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        this.doPost(request, response);
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        String param1 = request.getParameter("param1");
        IoConnector connector = new NioSocketConnector();
        connector.setHandler(new ClientHandler());
        connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));
        ConnectFuture future = connector.connect(new InetSocketAddress("127.0.0.1", 3456));
        future.awaitUninterruptibly();
        IoSession session = future.getSession();
        String flag = request.getLocalAddr() + UUID.randomUUID().toString();
        session.setAttribute("SendRequestFlag", flag);
        session.write(param1+"\n");
        session.getCloseFuture().awaitUninterruptibly();
        connector.dispose();
        Object result = ClientHandler.results.get(flag);
        ClientHandler.results.remove(flag);
        response.getWriter().write(result.toString());
    }

}

运行Servlet进行测试,当前这里的Socket服务器可以是任意的服务器。也可以用Mina来开发一个Socket服务器进行测试