java

位置:IT落伍者 >> java >> 浏览文章

疯狂Java讲义:使用NIO实现非阻塞Socket通信(2)[2]


发布日期:2021年07月05日
 
疯狂Java讲义:使用NIO实现非阻塞Socket通信(2)[2]

服务器端的Selector仅需要监听两种操作连接和读数据所以程序中分别处理了这两种操作如程序中②和③代码所示处理连接操作之时系统只需将接受连接后产生的SocketChannel注册到指定Selector对象即可处理读数据操作之时系统先从该Socket中读取数据再将数据写入Selector上注册的所有Channel

使用NIO来实现服务器时甚至无须使用ArrayList来保存服务器中所有SocketChannel因为所有的SocketChannel都需要注册到指定的Selector对象除此之外当客户端关闭时会导致服务器对应的Channel也抛出异常而且本程序只有一条线程如果该异常得不到处理将会导致整个服务器退出所以程序捕捉了这种异常并在处理异常时从Selector删除异常Channel的注册如程序中斜体字代码所示

本示例程序的客户端程序需要两个线程一个线程负责读取用户的键盘输入并将输入的内容写入SocketChannel中另一个线程则不断地查询Selector对象的select()方法的返回值

程序清单codes///NoBlock/NClientjava

public class NClient

{

//定义检测SocketChannel的Selector对象

private Selector selector = null;

//定义处理编码和解码的字符集

private Charset charset = CharsetforName(UTF

//客户端SocketChannel

private SocketChannel sc = null;

public void init()throws IOException

{

selector = Selectoropen()

InetSocketAddress isa = new InetSocketAddress(

//调用open静态方法创建连接到指定主机的SocketChannel

sc = SocketChannelopen(isa)

//设置该sc以非阻塞方式工作

scconfigureBlocking(false)

//将SocketChannel对象注册到指定Selector

scregister(selector SelectionKeyOP_READ)

//启动读取服务器端数据的线程

new ClientThread()start()

//创建键盘输入流

Scanner scan = new Scanner(Systemin)

while (scanhasNextLine())

{

//读取键盘输入

String line = scannextLine()

//将键盘输入的内容输出到SocketChannel中

scwrite(charsetencode(line))

}

}

//定义读取服务器数据的线程

private class ClientThread extends Thread

{

public void run()

{

try

{

while (selectorselect() >

{

//遍历每个有可用IO操作Channel对应的SelectionKey

for (SelectionKey sk : selectorselectedKeys())

{

//删除正在处理的SelectionKey

selectorselectedKeys()remove(sk)

//如果该SelectionKey对应的Channel中有可读的数据

if (skisReadable())

{

//使用NIO读取Channel中的数据

SocketChannel sc = (SocketChannel)skchannel()

ByteBuffer buff = ByteBufferallocate(

String content = ;

while(scread(buff) >

{

scread(buff)

buffflip()

content += charsetdecode(buff)

}

//打印输出读取的内容

Systemoutprintln(聊天信息 + content)

//为下一次读取作准备

skinterestOps(SelectionKeyOP_READ)

}

}

}

}

catch (IOException ex)

{

exprintStackTrace()

}

}

}

public static void main(String[] args)

throws IOException

{

new NClient()init()

}

}

相比之下客户端程序比服务器程序要简单多了客户端只有一条SocketChannel将该SocketChannel注册到指定Selector后程序启动另一条线程来监测该Selector即可

返回目录疯狂Java讲义

编辑推荐

Java程序性能优化让你的Java程序更快更稳定

新手学Java 编程

Java程序设计培训视频教程

[] []

               

上一篇:疯狂Java讲义:使用NIO实现非阻塞Socket通信(1)

下一篇:疯狂Java讲义:使用NIO实现非阻塞Socket通信(2)[1]