`

基于Nio的echo server和echo client

阅读更多
最近想学netty,但平常工作中NIO用的比较少,所以最近就复习了下NIO。自己写了个基于NIO的echo例子,代码挺简单的。


echo 服务端代码
package study.nio.echo;

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.Iterator;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class EchoServer implements Runnable {

	private static final Logger LOGGER = LoggerFactory.getLogger(EchoServer.class);

	private Selector selector;

	private ServerSocketChannel serverSocketChannel;

	private ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

	public EchoServer(int port) {

		try {

			selector = Selector.open();
			serverSocketChannel = ServerSocketChannel.open();
			serverSocketChannel.configureBlocking(false);
			serverSocketChannel.bind(new InetSocketAddress(port));
			serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

		} catch (IOException e) {

			LOGGER.error(e.getMessage());
			System.exit(0);
		}
	}

	@Override
	public void run() {

		if (selector.isOpen() == false) {

			LOGGER.warn("echo server selector is not start");
			return;
		}
		LOGGER.warn("echo server started");
		while (true) {

			try {

				selector.select();
				Set<SelectionKey> selectedKeys = selector.selectedKeys();
				Iterator<SelectionKey> keysIter = selectedKeys.iterator();
				while (keysIter.hasNext()) {

					SelectionKey key = keysIter.next();
					keysIter.remove();

					if (key.isAcceptable()) {

						ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
						SocketChannel sc = ssc.accept();
						sc.configureBlocking(false);
						LOGGER.info("echo server is connected");
						sc.register(selector, SelectionKey.OP_READ);
					} else if (key.isReadable()) {

						SocketChannel sc = (SocketChannel) key.channel();
						StringBuilder strb = new StringBuilder(1024);
						while (sc.read(byteBuffer) > 0) {

							byteBuffer.flip();
							byte[] bytes = new byte[byteBuffer.remaining()];
							byteBuffer.get(bytes);
							byteBuffer.clear();
							String msg = new String(bytes);
							LOGGER.info("echo server read msg:" + msg);
							strb.append(msg);
						}
						ByteBuffer writeBuffer = ByteBuffer.wrap(strb.toString().getBytes());
						LOGGER.info("{}", writeBuffer.position());
						LOGGER.info("{}", writeBuffer.limit());
						sc.write(writeBuffer);
					}
				}

			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

}





echo 客户端代码
package study.nio.echo;

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.SocketChannel;
import java.util.Iterator;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class EchoClient implements Runnable {

	private static final Logger LOGGER = LoggerFactory.getLogger(EchoClient.class);

	private Selector selector;

	private SocketChannel socketChannel;

	private ByteBuffer byteBuffer;

	public EchoClient(String ip, int port) {

		try {
			selector = Selector.open();
			socketChannel = SocketChannel.open();
			socketChannel.configureBlocking(false);
			socketChannel.connect(new InetSocketAddress(ip, port));
			socketChannel.register(selector, SelectionKey.OP_CONNECT);
		} catch (IOException e) {

			LOGGER.error(e.getMessage());
			System.exit(0);
		}
	}

	@Override
	public void run() {

		if (selector.isOpen() == false) {
			
			LOGGER.warn("echo client selector is not start");
			return;
		}
		LOGGER.warn("echo client started");
		while (true) {

			try {
				if (selector.isOpen() == false) {
					 LOGGER.warn("selector is closed");
					 break;
				}
				selector.select();
				Iterator<SelectionKey> ite = this.selector.selectedKeys().iterator();
				while (ite.hasNext()) {

					SelectionKey key = (SelectionKey) ite.next();
					ite.remove();
					if (key.isConnectable()) {

						SocketChannel channel = (SocketChannel) key.channel();
						// 如果正在连接,则完成连接
						if (channel.isConnectionPending()) {
							channel.finishConnect();
						}
						LOGGER.info("echo client is connected");
						// 设置成非阻塞
						channel.configureBlocking(false);
						channel.write(ByteBuffer.wrap("this echo client msg,over".getBytes()));
						channel.register(selector, SelectionKey.OP_READ);
					} else if (key.isReadable()) {
						
						SocketChannel sc = (SocketChannel) key.channel();
						StringBuilder strb = new StringBuilder(1024);
						while (sc.read(byteBuffer) > 0) {

							byteBuffer.flip();
							byte[] bytes = new byte[byteBuffer.remaining()];
							byteBuffer.get(bytes);
							byteBuffer.clear();
							String msg = new String(bytes);
							strb.append(msg);
						}
						LOGGER.info("echo client read msg:" + strb.toString());
						break;
					}
				}

			} catch (IOException e) {
				
				LOGGER.error(e.getMessage());
				System.exit(0);
			}

		}
	}

}



启动测试的代码

package study.nio.echo;

public class EchoTest1 {

	public static void main(String[] args) {
		
		EchoClient echoClient = new EchoClient("127.0.0.1", EchoTest.serverPort);
		echoClient.run();
	}
}


package study.nio.echo;

public class EchoTest1 {

	public static void main(String[] args) {
		
		EchoClient echoClient = new EchoClient("127.0.0.1", EchoTest.serverPort);
		echoClient.run();
	}
}

分享到:
评论

相关推荐

    Netty4EchoDemo

    Netty4EchoDemo是一个基于Netty 4框架实现的简单回显客户端(echo client)和服务器(echo server)示例。这个项目适用于那些想要学习如何使用Netty进行网络编程的开发者,尤其是对Java NIO(非阻塞I/O)感兴趣的...

    DotNetty源码、编码解码器,IdleStateHandler心跳机制

    在EchoServer和EchoClient示例中,我们可能会看到这些自定义编码解码器的用法,它们确保数据在客户端和服务器之间正确地传输。 2. **IdleStateHandler心跳机制**:在长时间无数据交换的网络连接中,...

    clj-async-tcp-echo-nio.2:Clojure 中使用 Java 7 NIO.2 的异步 TCP 回显客户端服务器

    clj-async-tcp-echo-nio.2 Clojure 中的异步 TCP 回显客户端/服务器,使用 Java 7 NIO.2。 Java 文档是详尽的,即使不一定是示例的最佳来源。 您可以使用 、 、 和获得所需的背景。用法在一个 REPL 中,启动一个...

    mina2推送demo客户端

    MINA2基于NIO(Non-blocking I/O)模型,允许在单个线程中处理多个连接,提高了系统并发能力。在"echo_client_udp"中,当客户端发送数据后,MINA2会异步等待服务器的响应,这样可以有效地避免线程阻塞,提高系统...

    【打天下篇】Netty实战.zip

    # Netty 实战 第二章节 ...echo server \ client by netty nio socket ``` # 启动 ``` server 端启动设置 端口 java -jar xxx.jar 9090 client 端启动设置 目标地址 目标端口 java -jar xxx.jar localhost 9090 ```

    关于java的一些基本程序

    2. **uclt.java** 和 **usvr.java**:这些文件名可能是"用户客户端"(UserClient)和"用户服务器"(UserServer)的缩写。它们可能展示了如何构建更复杂的客户端-服务器应用程序,可能涉及到用户交互和数据交换。在...

    服务端基于MINA2的UDP双向通信Demo演示(Java客户端)

    在压缩包中,文件名为“echo_client_udp”可能表示这是一个回声客户端的实现。回声客户端通常会发送数据到服务器,然后接收服务器返回的相同数据,以此来验证通信链路的正确性和性能。在这个示例中,客户端可能使用...

    高性能网络通信框架Netty从入门到核心源码剖析.rar

    2. 快速启动:通过编写一个简单的Echo Server和Client,展示Netty的基本使用,包括Bootstrap、ServerBootstrap、Channel、Handler等关键概念。 3. 事件驱动模型:解释Netty的NIO(非阻塞I/O)事件模型,包括...

    Android C++高级编程:使用NDK_Onur Cinar, 于红PDF电子书下载 带书签目录 完整版

    9.3 将原生UDP Client方法加入Echo Client Activity中 225 9.4 实现原生UDP Client 226 9.5 运行UDP Sockets示例 228 9.5.1 连通UDP的模拟器 228 9.5.2 启动Echo UDP Client 229 9.6 小结 229 第10章 POSIX ...

    一款Android平台UDP双向通信源码

    在Android Echo Client UDP项目中,我们可能找到了以下组件和概念: 1. **DatagramSocket**:UDP通信的核心组件,它用于发送和接收数据报(datagrams)。在这个客户端中,DatagramSocket创建并配置以连接到服务器的...

    Java Socket编程实例(五)- NIO UDP实践

    Java Socket编程中的NIO(非阻塞I/O)在UDP通信中的应用主要涉及到高效的数据传输和并发处理。...通过理解并掌握`EchoProtocol`和`UDPEchoSelectorProtocol`的实现,开发者能够更好地理解和运用NIO在UDP通信中的功能。

    socket通信.rar

    这个"socket通信.rar"文件可能包含了一些简单的Java Socket编程示例,例如“Echo Server”(服务器接收客户端发送的信息并原样返回)和“Client”(向服务器发送数据并接收响应)。通过学习和运行这些示例,你可以更...

    学习hadoop_源代码,RPC_部分

    Hadoop 的 `Server` 类基于 NIO(非阻塞 I/O)实现,主要负责接收和处理来自客户端的请求。具体来说: - **Listener 类** 负责监听 Socket 并创建任务交给处理器线程。 - **NIO** 是通过非阻塞方式处理 I/O 操作,...

    java精典编程100例

    通过对《Java经典编程100例》中的两个例子——Server端编程和Client端编程的详细介绍,我们不仅了解了Java网络编程的基本原理和技术要点,还掌握了如何使用Java编写简单的服务器端和客户端程序的方法。这对于初学者...

    java多线程Socket简单实现

    "消息,并回应"Echo: Hello, Server!"。客户端则打印出服务器的响应。 通过这种方式,Java多线程Socket实现可以构建出高并发、实时交互的网络应用,如聊天室、文件传输等。然而,实际开发中还需要考虑异常处理、...

    netty参考文档

    3. **时间服务器与客户端**(Writing a Time Server and Client):实现一个 TCP 服务器与客户端,服务器端接收请求并返回当前时间。 4. **处理流式传输**(Dealing with a Stream-based Transport):针对 TCP 连接...

    netty-3.2.5终极手册

    - **Echo Server**:与丢弃服务器不同,回声服务器会将接收到的数据原样返回给客户端。 - **Time Server**:时间服务器接收客户端请求后返回当前的时间戳。 - **Time Client**:与时间服务器配对使用的客户端程序,...

    Java网络编程UDP

    Java网络编程中的UDP(User Datagram Protocol)是一种无连接的、不可靠的传输协议,它相比TCP(Transmission Control Protocol)在速度上更快,因为不需要建立和维护连接,也不保证数据包的顺序和可靠性。...

    java网络编程

    - **非阻塞IO**:Java NIO (New IO) 提供了一种新的IO操作方式,使得程序可以在不等待数据准备好时就继续执行其他任务,从而提高了性能。 - **SSL/TLS安全通信**:为了保护数据的安全,Java提供了SSL/TLS支持,可以...

Global site tag (gtag.js) - Google Analytics