17【hutool】hutool-socket

727 阅读2分钟

该系列文章主要是对 hutool 工具类的介绍,详情可以参考

hutool.cn/docs

在开发网络应用程序的时候,我们又会遇到Socket这个概念。Socket是一个抽象概念,一个应用程序通过一个Socket来建立一个远程连接,而Socket内部通过TCP/IP协议把数据传输到网络

Java共支持3种网络编程IO模式:BIO,NIO,AIO

  • BIO 同步阻塞 IO
  • NIO 同步非阻塞 IO
  • AIO 异步非阻塞 IO

hutool只针对NIO和AIO做了简单的封装,用于简化Socket异步开发。

1 NIO

服务端

public class NioServerTest {

	public static void main(String[] args) {
		NioServer server = new NioServer(8080);
		server.setChannelHandler((sc)->{
			ByteBuffer readBuffer = ByteBuffer.allocate(1024);
			try{
				//从channel读数据到缓冲区
				int readBytes = sc.read(readBuffer);
				if (readBytes > 0) {
					//Flips this buffer.  The limit is set to the current position and then
					// the position is set to zero,就是表示要从起始位置开始读取数据
					readBuffer.flip();
					//eturns the number of elements between the current position and the  limit.
					// 要读取的字节长度
					byte[] bytes = new byte[readBuffer.remaining()];
					//将缓冲区的数据读到bytes数组
					readBuffer.get(bytes);
					String body = StrUtil.utf8Str(bytes);
					Console.log("[{}]: {}", sc.getRemoteAddress(), body);

					doWrite(sc, body);
				} else if (readBytes < 0) {
					IoUtil.close(sc);
				}
			} catch (IOException e){
				throw new IORuntimeException(e);
			}
		});
		server.listen();
	}

	public static void doWrite(SocketChannel channel, String response) throws IOException {
		response = "收到消息:" + response;
		//将缓冲数据写入渠道,返回给客户端
		channel.write(BufferUtil.createUtf8(response));
	}
}

客户端

public class NioClientTest {

	public static void main(String[] args) {
		NioClient client = new NioClient("127.0.0.1", 8080);
		client.setChannelHandler((sc)->{
			ByteBuffer readBuffer = ByteBuffer.allocate(1024);
			//从channel读数据到缓冲区
			int readBytes = sc.read(readBuffer);
			if (readBytes > 0) {
				// Flips this buffer.  The limit is set to the current position and then
				// the position is set to zero,就是表示要从起始位置开始读取数据
				readBuffer.flip();
				//returns the number of elements between the current position and the  limit.
				// 要读取的字节长度
				byte[] bytes = new byte[readBuffer.remaining()];
				//将缓冲区的数据读到bytes数组
				readBuffer.get(bytes);
				String body = StrUtil.utf8Str(bytes);
				Console.log("[{}]: {}", sc.getRemoteAddress(), body);
			} else if (readBytes < 0) {
				sc.close();
			}
		});

		client.listen();
		client.write(BufferUtil.createUtf8("你好。\n"));
		client.write(BufferUtil.createUtf8("你好2。"));

		// 在控制台向服务器端发送数据
		Console.log("请输入发送的消息:");
		Scanner scanner = new Scanner(System.in);
		while (scanner.hasNextLine()) {
			String request = scanner.nextLine();
			if (request != null && request.trim().length() > 0) {
				client.write(BufferUtil.createUtf8(request));
			}
		}
	}
}

2 AIO

服务端

public class AioServerTest {
	
	public static void main(String[] args) {
		
		@SuppressWarnings("resource")
		AioServer aioServer = new AioServer(8899);
		aioServer.setIoAction(new SimpleIoAction() {
			
			@Override
			public void accept(AioSession session) {
				StaticLog.debug("【客户端】:{} 连接。", session.getRemoteAddress());
				session.write(BufferUtil.createUtf8("=== Welcome to Hutool socket server. ==="));
			}
			
			@Override
			public void doAction(AioSession session, ByteBuffer data) {
				Console.log(data);
				
				if(false == data.hasRemaining()) {
					StringBuilder response = StrUtil.builder()//
							.append("HTTP/1.1 200 OK\r\n")//
							.append("Date: ").append(DateUtil.formatHttpDate(DateUtil.date())).append("\r\n")//
							.append("Content-Type: text/html; charset=UTF-8\r\n")//
							.append("\r\n")
							.append("Hello Hutool socket");//
					session.writeAndClose(BufferUtil.createUtf8(response));
				}else {
					session.read();
				}
			}
		}).start(true);
	}
}

客户端

public class AioClientTest {
	public static void main(String[] args) throws IOException {
		final AsynchronousChannelGroup GROUP = AsynchronousChannelGroup.withFixedThreadPool(//
				Runtime.getRuntime().availableProcessors(), // 默认线程池大小
				ThreadFactoryBuilder.create().setNamePrefix("Huool-socket-").build()//
		);

		AioClient client = new AioClient(new InetSocketAddress("localhost", 8899), new SimpleIoAction() {

			@Override
			public void doAction(AioSession session, ByteBuffer data) {
				if(data.hasRemaining()) {
					Console.log(StrUtil.utf8Str(data));
					session.read();
				}
				Console.log("OK");
			}
		});

		client.write(ByteBuffer.wrap("Hello".getBytes()));
		client.read();

		client.close();
	}
}