以前一直用的是“ervery thread per connection”的服务器端模式,今天试了下NIO非阻塞模式的服务器。 不过java不能实现I/O完成端口模型,这点很遗憾。

峨山县网站制作公司哪家好,找成都创新互联!从网页设计、网站建设、微信开发、APP开发、响应式网站等网站项目制作,到程序开发,运营维护。成都创新互联从2013年开始到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选成都创新互联。
- package com.vista.Server;
 - import java.io.IOException;
 - import java.net.InetSocketAddress;
 - import java.net.ServerSocket;
 - 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.LinkedList;
 - import java.util.Set;
 - public class SelectorServer
 - {
 - private static int DEFAULT_SERVERPORT = 6018;//默认端口
 - private static int DEFAULT_BUFFERSIZE = 1024;//默认缓冲区大小为1024字节
 - private ServerSocketChannel channel;
 - private LinkedList
 clients; - private Selector readSelector;
 - private ByteBuffer buffer;//字节缓冲区
 - private int port;
 - public SelectorServer(int port) throws IOException
 - {
 - this.port = port;
 - this.clients = new LinkedList
 (); - this.channel = null;
 - this.readSelector = Selector.open();//打开选择器
 - this.buffer = ByteBuffer.allocate(DEFAULT_BUFFERSIZE);
 - }
 - // 服务器程序在服务循环中调用sericeClients()方法为已接受的客户服务
 - public void serviceClients()throws IOException
 - {
 - Set keys;
 - Iterator it;
 - SelectionKey key;
 - SocketChannel client;
 - // 在readSelector上调用select()方法,参数1代表如果调用select的时候 那么阻塞最多1秒钟等待可用的客户端连接
 - if(readSelector.select(1) > 0)
 - {
 - keys = readSelector.selectedKeys(); // 取得代表端通道的键集合
 - it = keys.iterator();
 - // 遍历,为每一个客户服务
 - while(it.hasNext())
 - {
 - key = (SelectionKey)it.next();
 - if(key.isReadable())
 - { // 如果通道可读,那么读此通道到buffer中
 - int bytes;
 - client = (SocketChannel)key.channel();// 取得键对应的通道
 - buffer.clear(); // 清空缓冲区中的内容,设置好position,limit,准备接受数据
 - bytes = client.read(buffer); // 从通道中读数据到缓冲中,返回读取得字节数
 - if(bytes >= 0)
 - {
 - buffer.flip(); // 准备将缓冲中的数据写回到通道中
 - client.write(buffer); // 数据写回到通道中
 - }
 - else if(bytes < 0)
 - { // 如果返回小于零的值代表读到了流的末尾
 - clients.remove(client);
 - // 通道关闭时,选择键也被取消
 - client.close();
 - }
 - }
 - }
 - }
 - }
 - public void registerClient(SocketChannel client) throws IOException
 - {// 配置和注册代表客户连接的通道对象
 - client.configureBlocking(false); // 设置此通道使用非阻塞模式
 - client.register(readSelector, SelectionKey.OP_READ); // 将这个通道注册到选择器上
 - clients.add(client); //保存这个通道对象
 - }
 - public void listen() throws IOException
 - { //服务器开始监听端口,提供服务
 - ServerSocket socket;
 - SocketChannel client;
 - channel = ServerSocketChannel.open(); // 打开通道
 - socket = channel.socket(); //得到与通到相关的socket对象
 - socket.bind(new InetSocketAddress(port), 10); //将scoket榜定在制定的端口上
 - //配置通到使用非阻塞模式,在非阻塞模式下,可以编写多道程序同时避免使用复杂的多线程
 - channel.configureBlocking(false);
 - try
 - {
 - while(true)
 - {// 与通常的程序不同,这里使用channel.accpet()接受客户端连接请求,而不是在socket对象上调用accept(),这里在调用accept()方法时如果通道配置为非阻塞模式,那么accept()方法立即返回null,并不阻塞
 - client = channel.accept();
 - if(client != null)
 - {
 - registerClient(client); // 注册客户信息
 - }
 - serviceClients(); // 为以连接的客户服务
 - }
 - }
 - finally
 - {
 - socket.close(); // 关闭socket,关闭socket会同时关闭与此socket关联的通道
 - }
 - }
 - public static void main(String[] args) throws IOException
 - {
 - System.out.println("服务器启动");
 - SelectorServer server = new SelectorServer(SelectorServer.DEFAULT_SERVERPORT);
 - server.listen(); //服务器开始监听端口,提供服务
 - }
 - }
 
修改版本:
- package com.vista.Server;
 - import java.io.BufferedWriter;
 - import java.io.FileInputStream;
 - import java.io.IOException;
 - import java.io.OutputStreamWriter;
 - import java.io.PrintWriter;
 - import java.net.InetSocketAddress;
 - import java.net.ServerSocket;
 - import java.nio.ByteBuffer;
 - import java.nio.CharBuffer;
 - import java.nio.channels.FileChannel;
 - 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.nio.charset.CharsetDecoder;
 - import java.util.Iterator;
 - import java.util.LinkedList;
 - import java.util.Set;
 - public class SelectorServer
 - {
 - private static int DEFAULT_SERVERPORT = 6018;//默认端口
 - private static int DEFAULT_BUFFERSIZE = 1024;//默认缓冲区大小为1024字节
 - private static String DEFAULT_CHARSET = "GB2312";//默认码集
 - private static String DEFAULT_FILENAME = "bigfile.dat";
 - private ServerSocketChannel channel;
 - private LinkedList
 clients; - private Selector selector;//选择器
 - private ByteBuffer buffer;//字节缓冲区
 - private int port;
 - private Charset charset;//字符集
 - private CharsetDecoder decoder;//解码器
 - public SelectorServer(int port) throws IOException
 - {
 - this.port = port;
 - this.clients = new LinkedList
 (); - this.channel = null;
 - this.selector = Selector.open();//打开选择器
 - this.buffer = ByteBuffer.allocate(DEFAULT_BUFFERSIZE);
 - this.charset = Charset.forName(DEFAULT_CHARSET);
 - this.decoder = this.charset.newDecoder();
 - }
 - private class HandleClient
 - {
 - private String strGreeting = "welcome to VistaQQ";
 - public HandleClient() throws IOException
 - {
 - }
 - public String readBlock()
 - {//读块数据
 - return this.strGreeting;
 - }
 - public void close()
 - {
 - }
 - }
 - protected void handleKey(SelectionKey key) throws IOException
 - {//处理事件
 - if (key.isAcceptable())
 - { // 接收请求
 - ServerSocketChannel server = (ServerSocketChannel) key.channel();//取出对应的服务器通道
 - SocketChannel channel = server.accept();
 - channel.configureBlocking(false);
 - channel.register(selector, SelectionKey.OP_READ);//客户socket通道注册读操作
 - }
 - else if (key.isReadable())
 - { // 读信息
 - SocketChannel channel = (SocketChannel) key.channel();
 - int count = channel.read(this.buffer);
 - if (count > 0)
 - {
 - this.buffer.flip();
 - CharBuffer charBuffer = decoder.decode(this.buffer);
 - System.out.println("Client >>" + charBuffer.toString());
 - SelectionKey wKey = channel.register(selector,
 - SelectionKey.OP_WRITE);//为客户sockt通道注册写操作
 - wKey.attach(new HandleClient());
 - }
 - else
 - {//客户已经断开
 - channel.close();
 - }
 - this.buffer.clear();//清空缓冲区
 - }
 - else if (key.isWritable())
 - { // 写事件
 - SocketChannel channel = (SocketChannel) key.channel();
 - HandleClient handle = (HandleClient) key.attachment();//取出处理者
 - ByteBuffer block = ByteBuffer.wrap(handle.readBlock().getBytes());
 - channel.write(block);
 - // channel.socket().getInputStream().(block);
 - // PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
 - // channel.socket().getOutputStream())), true);
 - // out.write(block.toString());
 - }
 - }
 - public void listen() throws IOException
 - { //服务器开始监听端口,提供服务
 - ServerSocket socket;
 - channel = ServerSocketChannel.open(); // 打开通道
 - socket = channel.socket(); //得到与通到相关的socket对象
 - socket.bind(new InetSocketAddress(port)); //将scoket榜定在制定的端口上
 - //配置通到使用非阻塞模式,在非阻塞模式下,可以编写多道程序同时避免使用复杂的多线程
 - channel.configureBlocking(false);
 - channel.register(selector, SelectionKey.OP_ACCEPT);
 - try
 - {
 - while(true)
 - {// 与通常的程序不同,这里使用channel.accpet()接受客户端连接请求,而不是在socket对象上调用accept(),这里在调用accept()方法时如果通道配置为非阻塞模式,那么accept()方法立即返回null,并不阻塞
 - this.selector.select();
 - Iterator iter = this.selector.selectedKeys().iterator();
 - while(iter.hasNext())
 - {
 - SelectionKey key = (SelectionKey)iter.next();
 - iter.remove();
 - this.handleKey(key);
 - }
 - }
 - }
 - catch(IOException ex)
 - {
 - ex.printStackTrace();
 - }
 - }
 - public static void main(String[] args) throws IOException
 - {
 - System.out.println("服务器启动");
 - SelectorServer server = new SelectorServer(SelectorServer.DEFAULT_SERVERPORT);
 - server.listen(); //服务器开始监听端口,提供服务
 - }
 - }
 
                网页题目:JavaNIO非阻塞服务器示例
                
                本文链接:http://www.csdahua.cn/qtweb/news13/3663.html
            
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网