Java服务器 混合阻塞和非阻塞模式例子



EchoServer

package thread2;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;

public class EchoServer {

	private Selector selector = null;
	private ServerSocketChannel serverSocketChannel = null;
	private int port = 8000;
	private Charset charset = Charset.forName("GBK");

	public EchoServer() throws IOException {
		selector = Selector.open();
		serverSocketChannel = ServerSocketChannel.open();
		serverSocketChannel.socket().setReuseAddress(true);
		serverSocketChannel.socket().bind(new InetSocketAddress(port));
		System.out.println("Service Start");
	}

	public void accept() {
		for (;;) {
			try {
				SocketChannel socketChannel = serverSocketChannel.accept();
				System.out.println("recive client:"
						+ socketChannel.socket().getInetAddress() + ":"
						+ socketChannel.socket().getPort());
				socketChannel.configureBlocking(false);
				ByteBuffer buffer = ByteBuffer.allocate(1024);
				synchronized (gate) {
					selector.wakeup();
					socketChannel.register(selector, SelectionKey.OP_READ
							| SelectionKey.OP_WRITE, buffer);

				}

			} catch (IOException e) {
				// TODO: handle exception
				e.printStackTrace();
			}
		}
	}

	private Object gate = new Object();

	public void service() throws IOException {
		for (;;) {
			synchronized (gate) {
			}
			int n = selector.select();
			if (n == 0)
				continue;
			Set<SelectionKey> readyKeys = selector.selectedKeys();
			Iterator it = readyKeys.iterator();
			while (it.hasNext()) {
				SelectionKey key = null;
				try {
					key = (SelectionKey) it.next();
					it.remove();
					if (key.isReadable()) {
						receive(key);

					}
					if (key.isWritable()) {
						send(key);
					}

				} catch (IOException e) {
					// TODO: handle exception
					e.printStackTrace();
					try {
						if (key != null) {
							key.cancel();
							key.channel().close();

						}
					} catch (Exception e2) {
						// TODO: handle exception
						e2.printStackTrace();
					}
				}
			}
		}
	}

	public void send(SelectionKey key) throws IOException {
		ByteBuffer buffer = (ByteBuffer) key.attachment();
		SocketChannel socketChannel = (SocketChannel) key.channel();
		buffer.flip();
		String data = decode(buffer);
		if (data.indexOf("\n") == -1)
			return;
		String outputData = data.substring(0, data.indexOf("\n") + 1);
		System.out.print(outputData);
		ByteBuffer outputBuffer = encode("echo:" + outputData);
		while (outputBuffer.hasRemaining())
			socketChannel.write(outputBuffer);
		ByteBuffer temp = encode(outputData);
		buffer.position(temp.limit());
		buffer.compact();

		if (outputData.equals("bye\r\n")) {
			key.cancel();
			socketChannel.close();
			System.out.println("关闭与客户的连接");
		}
	}

	public void receive(SelectionKey key) throws IOException {
		ByteBuffer buffer = (ByteBuffer) key.attachment();

		SocketChannel socketChannel = (SocketChannel) key.channel();
		ByteBuffer readBuffer = ByteBuffer.allocate(32);
		socketChannel.read(readBuffer);
		readBuffer.flip();

		buffer.limit(buffer.capacity());
		buffer.put(readBuffer);

	}

	public String decode(ByteBuffer buffer) {
		CharBuffer charBuffer = charset.decode(buffer);
		return charBuffer.toString();
	}

	public ByteBuffer encode(String str) {
		return charset.encode(str);
	}

	
	public static void main(String args[]) throws Exception {
		final EchoServer server = new EchoServer();
		Thread accept = new Thread(){
			public void run() {
				server.accept();
			}
		};
		accept.start();
		server.service();
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杜甲同学

感谢打赏,我会继续努力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值