Android 中使用Socket来实现客户端和服务器端(使用MINA框架)

首先使用MINA框架要先下载框架所需的JAR包,这里给出我打包好的资源,需要的可以下载点击打开链接

言归正传,先来介绍服务器端(因为这个框架主要是用在服务器的,所以用在android设备上会比较耗资源,我用了这个测试工具,一般二十几台设备还是可以的)

1、创建一个非阻塞的Server端的Socket

IoAcceptor accept = new NioSocketAcceptor();

2、设置过滤器,这里可以使用MINA提供的文本换行符编解码器也可以用自定义的编解码器

(1)提供的

TextLineCodecFactory lineCode = new TextLineCodecFactory(Charset.forName("UTF-8"),LineDelimiter.WINDOWS.getValue(),LineDelimiter.WINDOWS.getValue());

这里还可以设置编解码的最大行的长度lineCode.setDecoderMaxLineLength(1024);lineCode.setEncoderMaxLineLength(1024);

然后acceptor.getFilterChain().addLast("codec",new ProtocolCodecFilter(lineCode));

(2)使用自定义的编解码器

这里先定义一个编解码的工厂类CharsetCodeFactory 实现ProtocolCodecFactory

public class CharsetCodecFactory implements ProtocolCodecFactory {

	@Override
	public ProtocolDecoder getDecoder(IoSession session) throws Exception {//返回一个解码器
		return new CharsetDecoder();
	}

	@Override
	public ProtocolEncoder getEncoder(IoSession session) throws Exception {//返回一个编码器
		return new CharsetEncoder();
	}
}
编写编码器类

public class CharsetEncoder implements ProtocolEncoder {
	private static String TAG = "CharsetEncoder";
	private final static Charset charset = Charset.forName("UTF-8");

	@Override
	public void dispose(IoSession session) throws Exception {
		Log.d(TAG, "#############dispose############");
	}

	@Override
	public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
		Log.d(TAG, "#############字符编码############");
		IoBuffer buff = IoBuffer.allocate(100).setAutoExpand(true);//设置缓冲区,根据传输内容大小自动变更
		buff.putString(message.toString(), charset.newEncoder());//设置字符编码
		// put 当前系统默认换行符
		buff.putString(LineDelimiter.DEFAULT.getValue(), charset.newEncoder());
		// 为下一次读取数据做准备
		buff.flip();
		out.write(buff);
	}
}
编写解码器类

public class CharsetDecoder implements ProtocolDecoder {
 
   private static String TAG = "CharsetDecoder";
    
    private final static Charset charset = Charset.forName("UTF-8");    
    // 可变的IoBuffer数据缓冲区
    private IoBuffer buff = IoBuffer.allocate(100).setAutoExpand(true);
    
    @Override
    public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
    	Log.d(TAG,"#########decode#########");
        
        // 如果有消息
        while (in.hasRemaining()) {
            // 判断消息是否是结束符,不同平台的结束符也不一样;
            // windows换行符(\r\n)就认为是一个完整消息的结束符了; UNIX 是\n;MAC 是\r
            byte b = in.get();
            if (b == '\n') {
                buff.flip();
                byte[] bytes = new byte[buff.limit()];
                buff.get(bytes);
                String message = new String(bytes, charset);
                
                buff = IoBuffer.allocate(100).setAutoExpand(true);
                
                // 如果结束了,就写入转码后的数据
                out.write(message);
                Log.d(TAG,"message: " + message);
            } else {
                buff.put(b);
            }
        }
    }
 
    @Override
    public void dispose(IoSession session) throws Exception {
    	Log.d(TAG,"#########dispose#########");
    	Log.d(TAG,"============"+session.getCurrentWriteMessage());
    }
 
    @Override
    public void finishDecode(IoSession session, ProtocolDecoderOutput out) throws Exception {
    	Log.d(TAG,"#########完成解码#########");
    }
}
3、设置读取数据的缓冲区大小

acceptor.getSessionConfig().setReadBufferSize(2048);

4、设置读写的通道如果10秒内无操作就进入空闲状态

acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE,10);

5、为接收器设置管理服务(核心处理)

acceptor.setHandler(new MyServerHandler());

其中MyServerHandler为封装好的逻辑处理类

/**
 * 
 * @author huangdianhua
 * @date 2016年8月11日 下午1:03:51
 */
public class MyServerHandler extends IoHandlerAdapter {
	private static String TAG = "MyServerHandler";

	// 从端口接受消息,会响应此方法来对消息进行处理
	@Override
	public void messageReceived(IoSession session, Object message) throws Exception {
		String msg = message.toString();
		Log.d(TAG, "服务器接受消息成功..." + msg);
		// 拿到所有的客户端Session
		Collection sessions = session.getService().getManagedSessions().values();
		// 向所有客户端发送数据
		for (IoSession sess : sessions) {
			sess.write(msg);
		}
	}

	// 向客服端发送消息后会调用此方法
	@Override
	public void messageSent(IoSession session, Object message) throws Exception {
		Log.d(TAG, "服务器发送消息成功...");
		super.messageSent(session, message);
	}

	// 关闭与客户端的连接时会调用此方法
	@Override
	public void sessionClosed(IoSession session) throws Exception {
		Log.d(TAG, "服务器与客户端断开连接...");
		CloseFuture closeFuture = session.close(true);
		closeFuture.addListener(new IoFutureListener() {
			public void operationComplete(IoFuture future) {
				if (future instanceof CloseFuture) {
					((CloseFuture) future).setClosed();
				}
			};
		});
	}

	// 服务器与客户端创建连接
	@Override
	public void sessionCreated(IoSession session) throws Exception {
		Log.d(TAG, "服务器与客户端创建连接...");

	}

	// 服务器与客户端连接打开
	@Override
	public void sessionOpened(IoSession session) throws Exception {
		Log.d(TAG, "服务器与客户端连接打开...");
		super.sessionOpened(session);
	}

	@Override
	public void sessionIdle(IoSession session, IdleStatus status) throws Exception {
		Log.d(TAG, "服务器进入空闲状态...");
		super.sessionIdle(session, status);
	}

	@Override
	public void exceptionCaught(IoSession session, Throwable cause) throws Exception {
		Log.d(TAG, "服务器发送异常...");
		super.exceptionCaught(session, cause);
	}
}

6、绑定端口

acceptor.bind(new InetSocketAddress(PORT));

以上就是服务器端的具体实现方式

下面介绍客户端的具体实现过程

1、创建一个连接器

IoConnector connector = new NioSocketConnector();

2、设置超时时间

connector.setConnectTimeoutMillis(3000);

3、添加过滤器(这个和服务器端的设置一样)

4、为接收器设置管理服务(这个也是和服务器是一样设置的)

connector.setHandler(new MinaClientHandler());

/**
 * 
 * @author huangdianhua
 * @date 2016年8月11日 下午4:28:11
 */
public class MinaClientHandler extends IoHandlerAdapter {
	private static String TAG = "MinaClientHandler";

	@Override
	public void exceptionCaught(IoSession session, Throwable cause)
			throws Exception {
		Log.d(TAG, "客户端发生异常" + cause.getMessage());
		super.exceptionCaught(session, cause);
	}

	@Override
	public void messageReceived(IoSession session, Object message)
			throws Exception {
		String msg = message.toString();
		Log.d(TAG, "客户端接收到的信息为:" + msg);

		Intent intent = new Intent();
		intent.setAction(CommonUtil.SEND_BROADCAST);
		intent.putExtra("name", msg);
		MyApplication.mContext.sendBroadcast(intent);
		super.messageReceived(session, message);
	}

	@Override
	public void messageSent(IoSession session, Object message) throws Exception {
		// TODO Auto-generated method stub
		super.messageSent(session, message);
	}
}


5、为连接器创建连接

ConnectFuture future = connector.connect(new InetSocketAddress(IP,PORT));//创建链接

future.awaitUninterruptibly();//等待连接创建完成

6、获得创建连接得到的session

session = future.getSession();

session.write("start");//写入信息

以上就是客户端的具体实现过程

参考点击打开链接

你可能感兴趣的:(Socket)