代碼分爲客戶端、服務端以及調試代碼
客戶端:
package test.nio.tcp;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
class AsyncClient
{
private SocketChannel sc;
private final int MAX_LENGTH = 1024;
private ByteBuffer r_buff = ByteBuffer.allocate(MAX_LENGTH);
private ByteBuffer w_buff = ByteBuffer.allocate(MAX_LENGTH);
private static String host;
private static int port = 6000;
public AsyncClient()
{
try
{
InetSocketAddress addr = new InetSocketAddress(host, port);
// 生成一个socketchannel
sc = SocketChannel.open();
// 连接到server
sc.connect(addr);
while (!sc.finishConnect());
System.out.println("connection has been established!...");
while (true)
{
// // 回射消息
// String echo = null;
// try
// {
// System.err.println("Enter msg you'd like to send: ");
// BufferedReader br = new BufferedReader(
// new InputStreamReader(System.in));
// // 输入回射消息
// echo = br.readLine();
// echo = "send [test] to server.";
//
// // 把回射消息放入w_buff中
// w_buff.clear();
// w_buff.put(echo.getBytes());
// w_buff.flip();
// }
// catch (IOException ioe)
// {
// System.err.println("sth. is wrong with br.readline() ");
// }
//
// // 发送消息
// while (w_buff.hasRemaining())
// sc.write(w_buff);
// w_buff.clear();
// 进入接收状态
Rec();
// 间隔1秒
//Thread.currentThread().sleep(1000);
}
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
// catch (InterruptedException ie)
// {
// ie.printStackTrace();
// }
}
// //////////
// 读取server端发回的数据,并显示
public void Rec() throws IOException
{
int count;
r_buff.clear();
count = sc.read(r_buff);
r_buff.flip();
byte[] temp = new byte[r_buff.limit()];
r_buff.get(temp);
System.out.println("reply is [" + count + "] long, and content is: "
+ new String(temp));
}
public static void main(String args[])
{
// if (args.length < 1)
// {// 输入需有主机名或IP地址
// try
// {
// System.err.println("Enter host name: ");
// BufferedReader br = new BufferedReader(new InputStreamReader(
// System.in));
// host = br.readLine();
// }
// catch (IOException ioe)
// {
// System.err.println("sth. is wrong with br.readline() ");
// }
// }
// else if (args.length == 1)
// {
// host = args[0];
// }
// else if (args.length > 1)
// {
// host = args[0];
// port = Integer.parseInt(args[1]);
// }
host = "127.0.0.1";
port = 6000;
new AsyncClient();
}
}
服務端:
package test.nio.tcp;
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;
class AsyncServer implements Runnable
{
private ByteBuffer r_buff = ByteBuffer.allocate(1024);
private ByteBuffer w_buff = ByteBuffer.allocate(1024);
private static int port = 7890;
public AsyncServer()
{
new Thread(this).start();
}
public void run()
{
try
{
// 生成一个侦听端
ServerSocketChannel ssc = ServerSocketChannel.open();
// 将侦听端设为异步方式
ssc.configureBlocking(false);
// 生成一个信号监视器
Selector s = Selector.open();
// 侦听端绑定到一个端口
ssc.socket().bind(new InetSocketAddress(port));
// 设置侦听端所选的异步信号OP_ACCEPT
ssc.register(s, SelectionKey.OP_ACCEPT);
System.out.println("echo server has been set up ......");
while (true)
{
int n = s.select();
if (n == 0)
{// 没有指定的I/O事件发生
continue;
}
Iterator it = s.selectedKeys().iterator();
while (it.hasNext())
{
SelectionKey key = (SelectionKey) it.next();
if (key.isAcceptable())
{// 侦听端信号触发
ServerSocketChannel server = (ServerSocketChannel) key
.channel();
// 接受一个新的连接
SocketChannel sc = server.accept();
sc.configureBlocking(false);
// 设置该socket的异步信号OP_READ:当socket可读时
// 触发函数DealwithData();
sc.register(s, SelectionKey.OP_READ);
}
if (key.isReadable())
{// 某socket可读信号
DealwithData(key);
}
it.remove();
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
public void DealwithData(SelectionKey key) throws IOException
{
int count = 0;
// 由key获取指定socketchannel的引用
SocketChannel sc = (SocketChannel) key.channel();
r_buff.clear();
// 读取数据到r_buff
while ((count = sc.read(r_buff)) > 0);
// 确保r_buff可读
r_buff.flip();
w_buff.clear();
// 将r_buff内容拷入w_buff
w_buff.put(r_buff);
w_buff.flip();
// 将数据返回给客户端
EchoToClient(sc);
w_buff.clear();
r_buff.clear();
}
public void EchoToClient(SocketChannel sc) throws IOException
{
while (w_buff.hasRemaining())
sc.write(w_buff);
}
public static void main(String args[])
{
if (args.length > 0)
{
port = Integer.parseInt(args[0]);
}
new AsyncServer();
}
}
本地調試:
package test.nio.tcp;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
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;
/**
*
* @author Administrator
* @version
*/
public class NBTest
{
/** Creates new NBTest */
public NBTest()
{
}
public void startServer() throws Exception
{
int channels = 0;
int nKeys = 0;
//使用Selector
Selector selector = Selector.open();
//建立Channel 并绑定到9000端口
ServerSocketChannel ssc = ServerSocketChannel.open();
System.out.println("Bind Host["+InetAddress.getLocalHost().getHostName()+"] Port["+7890+"]");
InetSocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(),7890);
ssc.socket().bind(address);
//使设定non-blocking的方式。
ssc.configureBlocking(false);
//向Selector注册Channel及我们有兴趣的事件
SelectionKey s = ssc.register(selector, SelectionKey.OP_ACCEPT);
printKeyInfo(s);
while(true) // 不断的轮询
{
debug("NBTest: Starting select");
//Selector通过select方法通知我们我们感兴趣的事件发生了。
nKeys = selector.select();
//如果有我们注册的事情发生了,它的传回值就会大于0
if(nKeys > 0)
{
debug("NBTest: Number of keys after select operation: " +nKeys);
//Selector传回一组SelectionKeys
//我们从这些key中的channel()方法中取得我们刚刚注册的channel。
Set selectedKeys = selector.selectedKeys();
Iterator i = selectedKeys.iterator();
while(i.hasNext())
{
s = (SelectionKey) i.next();
printKeyInfo(s);
debug("NBTest: Nr Keys in selector: " +selector.keys().size());
//一个key被处理完成后,就都被从就绪关键字(ready keys)列表中除去
i.remove();
if(s.isAcceptable())
{
System.out.println("Receive a new socket.");
//从channel()中取得我们刚刚注册的channel。
Socket socket = ((ServerSocketChannel)s.channel()).accept().socket();
SocketChannel sc = socket.getChannel();
sc.configureBlocking(false);
sc.register(selector, SelectionKey.OP_READ |SelectionKey.OP_WRITE);
System.out.println(++channels);
}
else
{
debug("NBTest: Channel not acceptable");
}
}
}
else
{
debug("NBTest: Select finished without any keys.");
}
}
}
private static void debug(String s)
{
System.out.println(s);
}
private static void printKeyInfo(SelectionKey sk)
{
String s = new String();
s = "Att: " + (sk.attachment() == null ? "no" : "yes");
s += ", Read: " + sk.isReadable();
s += ", Acpt: " + sk.isAcceptable();
s += ", Cnct: " + sk.isConnectable();
s += ", Wrt: " + sk.isWritable();
s += ", Valid: " + sk.isValid();
s += ", Ops: " + sk.interestOps();
debug(s);
}
/**
* @param args the command line arguments
*/
public static void main (String args[])
{
NBTest nbTest = new NBTest();
try
{
nbTest.startServer();
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
相关推荐
Java NIO(New Input/Output)是一种用于处理I/O操作的非阻塞I/O模型,与传统的Java IO相比,它提供了更高的性能和更灵活的编程方式。NIO的核心概念包括Channel、Selector、SelectionKey和Buffer。 1. **Channel...
尽管Java IO功能强大,但其实现方式有时会显得较为复杂,特别是当需要处理不同类型的输入输出时,往往需要使用到多个类和接口。本文将对Java输入输出流进行一次全面的介绍,旨在帮助初学者快速理解并掌握这一重要...
Java中BIO、NIO和AIO的区别和应用场景 Java中IO模型有三种:BIO、NIO和AIO,下面我们来详细介绍它们的区别和应用场景。 BIO(Blocking I/O) BIO是Java中最古老的IO模型,它是同步并阻塞的。服务器的实现模式是一...
浅谈Java堆外内存之突破JVM枷锁 本文主要介绍了Java堆外内存的概念,包括JVM内存分配、JVM垃圾回收、堆外内存的垃圾回收等相关内容。Java开发者都知道,Java中不需要手动申请和释放内存,JVM会自动进行垃圾回收;而...
【标题】:“浅谈Tomcat一些细节配置” Tomcat,作为Apache软件基金会的开源项目,是Java Servlet和JavaServer Pages(JSP)的容器,也是Java EE Web应用程序的标准实现。在实际开发和部署中,对Tomcat进行适当的...
5. **优化任务执行**:尽量减少线程阻塞的时间,例如,避免长时间的IO操作,或者使用非阻塞的并发库如`java.nio`。 6. **监控与异常处理**:对线程池进行监控,记录线程的状态和执行情况,及时发现和处理异常,保证...
浅谈Tomcat三种运行模式 Tomcat服务器有三种运行模式:bio、nio和apr。每种模式都有其特点和优缺点,本文将对这三种模式进行详细的介绍。 bio模式 bio模式是Tomcat服务器的传统运行模式,也是Tomcat 7以下版本的...
Java网络编程中也有类似的概念,如BIO( Blocking I/O)、NIO(Non-blocking I/O)和AIO(Asynchronous I/O),它们分别对应上述模型的不同实现。其中,NIO和AIO在Java中提供了非阻塞和异步的网络通信能力,有助于...
"浅谈Android Studio导出javadoc文档操作及问题的解决" Android Studio是当前Android应用开发的主流IDE之一,但是在实际开发中,我们经常需要生成javadoc文档以便于其他开发者或团队成员了解我们的代码结构和设计...
- IO与NIO的区别:了解Java中传统IO和新IO(NIO)之间的区别,以及各自的使用场景。 - Synchronized和Lock的区别和用法:理解同步关键字synchronized和锁接口Lock的不同用法和优势。 - Final、Finally、Finalize的...
- **Java实现浅克隆与深克隆**:浅克隆复制对象本身及含有引用的对象地址,而深克隆则复制了对象本身及所有成员变量的值。 - **枚举可以序列化吗**:枚举类型默认实现了`Serializable`接口,因此可以直接进行序列化...
- **5.5 Java实现浅克隆与深克隆**:说明Java中克隆机制的两种形式及其应用场景。 - **5.6 枚举可以序列化吗**:探讨枚举类型的序列化可能性。 - **5.7 Java创建对象的方式**:列举并解释创建Java对象的各种方法。 -...
- **5.5 Java实现浅克隆与深克隆:** - **浅克隆**复制对象本身及包含的引用类型成员变量,但不会复制这些引用的对象。 - **深克隆**复制对象本身及其引用的所有对象。 - **5.6 枚举可以序列化吗:** - 枚举类...