java nio

package xx.xx.xx;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import org.apache.log4j.Logger;

import cn.istorm.gm.websocket.WebSocket;

public class Server {

	private static final Logger logger = Logger.getLogger(Server.class);

	//监听端口
	private static final int PORT = 18085;
	//读缓冲区大小
	private static final int READBUFFERSIZE = 2048;
	//写缓冲区大小
	private static final int WRITERBUFFERSIZE = 15;

	//读缓冲区
	private static ByteBuffer readbuffer = null;
	//写缓冲区
	private static ByteBuffer writerbuffer = null;
	//ip白名单
	private static Set<String> ip_set = null;

	//选择器
	private Selector selector;
	
	static {
		//读缓冲区实例
		readbuffer = ByteBuffer.allocate(READBUFFERSIZE);
		//写缓冲区实例
		writerbuffer = ByteBuffer.allocate(WRITERBUFFERSIZE);
		//ip白名单实例
		ip_set = new HashSet<String>();
		//读取配置文件IP白名单
		String ips = PropertiesUtils.getProperty("socket.server.ip");
		if (ips != null && ips != "") {
			ips = ips.trim();
			String[] ipArray = ips.split(",");
			for (String ip : ipArray) {
				ip = ip.trim();
				if (ip == "") {
					continue;
				}
				ip_set.add(ip);
			}
		}
	}
	
	public Server(int port) throws IOException {
		//开启一个socket服务
		ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
		//设置异步
		serverSocketChannel.configureBlocking(false);
		//绑定端口
		serverSocketChannel.socket().bind(new InetSocketAddress(port));
		//开启一个选择器
		this.selector = Selector.open();
		//注册监听事件
		serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
		logger.info("socket服务端开启服务成功,监听端口:" + port);
	}
	
	public Server() throws IOException {
		this(PORT);
	}

	//用一个线程循环监听
	public void listen() {
		new Thread(new Runnable() {

			@Override
			public void run() {
				while (true) {
					try {
						//监听,这里会阻塞
						int select = selector.select();
						if (select <= 0) {
							continue;
						}
					} catch (IOException e) {
						logger.error("socket服务端监听异常", e);
						continue;
					}
					//获取key集合
					Iterator<SelectionKey> it = selector.selectedKeys().iterator();
					while (it.hasNext()) {
						SelectionKey selectionKey = it.next();
						//删除key
						it.remove();
						//处理事件
						handle(selectionKey);
					}
				}
			}
		}).start();
		logger.info("socket服务端开启监听服务成功");
	}

	//处理事件
	private void handle(SelectionKey selectionKey) {
		switch (selectionKey.readyOps()) {
		case SelectionKey.OP_CONNECT:
			break;
		case SelectionKey.OP_ACCEPT:
			this.accept(selectionKey);
			break;
		case SelectionKey.OP_READ:
			this.read(selectionKey);
			break;
		case SelectionKey.OP_WRITE:
			this.writer(selectionKey);
			break;
		default:
			break;
		}
	}
	
	//接收连接事件
	private void accept(SelectionKey selectionKey) {
		SocketChannel client = null;
		try {
			client = ((ServerSocketChannel) selectionKey.channel()).accept();
			String remoteAddress = client.getRemoteAddress().toString().replaceAll("/", "");
			String remoteAddress1 = remoteAddress.substring(0, remoteAddress.indexOf(".", remoteAddress.indexOf(".") + 1));
			String remoteAddress2 = remoteAddress.substring(0, remoteAddress.lastIndexOf(":"));
			if (!ip_set.contains(remoteAddress1) && !ip_set.contains(remoteAddress2) && !ip_set.contains(remoteAddress)) {
				throw new RuntimeException("socket连接被强制关闭,原因:访问IP不在白名单内,来源地址:" + remoteAddress);
			}
			client.configureBlocking(false);
			client.register(this.selector, SelectionKey.OP_READ);
			logger.info("socket连接成功,来源地址:" + client.getRemoteAddress());
		} catch (Exception e) {
			logger.error("socket连接异常", e);
			try {if (client != null) {client.socket().close();client.close();}} catch (IOException e1) {logger.error("关闭socket异常", e1);}
		}
	}
	
	//读取消息事件
	private void read(SelectionKey selectionKey) {
		SocketChannel client = null;
		try {
			client = (SocketChannel) selectionKey.channel();
			readbuffer.clear();
			int count = client.read(readbuffer);
			if (count < 0) {
				throw new RuntimeException("socket读取到已关闭的连接");
			}
			readbuffer.flip();
			
			System.out.println(new String(readbuffer.array(), 0, count));
			
			client.register(this.selector, SelectionKey.OP_WRITE);
			logger.info("socket读取消息成功,共:" + count + "个字节,来源地址:" + client.getRemoteAddress());
		} catch (Exception e) {
			logger.error("socket读取消息异常", e);
			try {if (client != null) {client.socket().close();client.close();}} catch (IOException e1) {logger.error("关闭socket异常", e1);}
		}
	}
	
	//写出消息事件
	private void writer(SelectionKey selectionKey) {
		SocketChannel client = null;
		try {
			client = (SocketChannel) selectionKey.channel();
			writerbuffer.clear();
			writerbuffer.put("success".getBytes());
			writerbuffer.flip();
			client.write(writerbuffer);
			client.register(this.selector, SelectionKey.OP_READ);
			logger.info("socket写出消息成功");
		} catch (Exception e) {
			logger.error("socket写出消息异常", e);
			try {if (client != null) {client.socket().close();client.close();}} catch (IOException e1) {logger.error("关闭socket异常", e1);}
		}
	}

	public void close() {
		if (this.selector != null) {
			try {
				this.selector.close();
			} catch (Exception e) {
				logger.error("关闭selector异常", e);
			}
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值