采用Java nio 实现的一个简单的服务器

来源:互联网 发布:it平面设计 编辑:程序博客网 时间:2024/05/16 11:21

服务器代码:

package server.nio;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.Serializable;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.util.ArrayList;import java.util.concurrent.Callable;import java.util.concurrent.ConcurrentLinkedQueue;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class Server {    private static Logger log = LoggerFactory.getLogger(Server.class);    private static final Integer Default_Port = 9527;    private static final Integer Default_Timeout = 2000;    private static ConcurrentLinkedQueue<SocketChannel> workeQueue = new ConcurrentLinkedQueue<>();    private static ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());    private Integer port;    private Integer timeout;    public Server() {        this(Default_Port,Default_Timeout);    }    public Server(Integer port){        this(port,Default_Timeout);    }    public Server(Integer port,Integer timeout) throws IllegalArgumentException{        if(port == null) port = Default_Port;        if(timeout == null) timeout = Default_Timeout;        this.port = port;        this.timeout = timeout;        long st = System.currentTimeMillis();        try {            log.debug("服务器开始启动-->>");            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();            serverSocketChannel.configureBlocking(false);            serverSocketChannel.bind(new InetSocketAddress(Default_Port));            //启动监听workQueue队列的线程            log.debug("任务队列监听线程启动开始--->>");            startListener();            log.debug("任务队列监听线程启动完成---<<");            //启动服务器            long et = System.currentTimeMillis();            log.debug("服务器启动完成:--<<");            log.debug("启动耗时:"+(et-st));            start(serverSocketChannel);        } catch (IOException e) {            e.printStackTrace();        }    }    private void startListener() {        Thread t = new Thread(new Runnable() {            public void run() {                while(true){                    final SocketChannel sc = workeQueue.poll();                    try {                        if(sc != null){                            if(log.isDebugEnabled()){                                log.debug("开始处理客户端请求:"+sc);                            }                            executorService.submit(new Callable<Response>() {                                @Override                                public Response call() throws Exception {                                    //创建字节缓冲区                                    ByteBuffer bytes = ByteBuffer.allocate(64);                                    ArrayList<Byte> list = new ArrayList<>();                                    try {                                        //从通道中读取字节到缓冲区                                        while(sc.read(bytes) != -1){                                            bytes.flip();                                            //判断字节缓冲区是否已满                                            while(bytes.remaining() > 0){                                                //将缓冲区中的字节数组放到list中                                                //字节缓冲区满,但通道中的数据可能还没有读取完,因此需要将字节先保存起来                                                //最后统一处理(如果不这样做,可能会出现意外的结果:如最后转化成字符串,如不这样做,会因字节不完整而乱码)                                                list.add(bytes.get());                                                //清空字节缓冲区,以接收通道中剩余的数据                                            }                                            bytes.clear();                                        }                                        byte[] temp = new byte[list.size()];                                        //将list中的数据放到temp字节数组中                                        for(int i=0;i<list.size();i++){                                            temp[i] = list.get(i);                                        }                                        //反序列化开始                                        try{                                            ByteArrayInputStream bin = new ByteArrayInputStream(temp);                                            ObjectInputStream oin = new ObjectInputStream(bin);                                            Object obj = oin.readObject();//                                          Object obj = ObjectUtil.deserializeJdk(temp);                                            System.out.println(obj);                                        }catch(Exception e){                                            log.debug("反序列化对象失败:请检查是否实现Serializable接口:");                                            e.printStackTrace();                                        }                                        //反序列化开始结束                                    } catch (Exception e) {                                        e.printStackTrace();                                    }                                    //处理响应对象//                                  ByteArrayOutputStream baos = new ByteArrayOutputStream();//                                  ObjectOutputStream oos = new ObjectOutputStream(baos);//                                  //将返回的对象序列化//                                  oos.writeObject(response);//                                  //将byte数组转换成通道可以接受的ByteBuffer类型//                                  ByteBuffer writeBytes = ByteBuffer.wrap(baos.toByteArray());//                                  sc.write(writeBytes);//                                  sc.close();                                    return null;                                }                            });                        }                    } catch (Exception e) {                        e.printStackTrace();                    }finally{                        if(sc != null){                            log.debug("客户端链接:"+sc+":关闭");                        }else{                            try {                                Thread.sleep(2000);                            } catch (InterruptedException e) {                            }                            log.debug("等待连接....");                        }                    }                }            }        });        t.start();    }    private void start(ServerSocketChannel serverSocketChannel) {        while(true){            try {                SocketChannel socketChannel = serverSocketChannel.accept();                if(socketChannel != null){                    if(log.isDebugEnabled()){                        log.debug("客户端连接放进任务队列中:"+serverSocketChannel);                    }                    workeQueue.add(socketChannel);                }            } catch (IOException e) {                e.printStackTrace();            }        }    }    /**     * 响应对象     * @author Administrator     *     */    public class Response implements Serializable {//      private Integer status;//      //      private Integer code;//      //      private String desc;//      //      private Object data;////      //      public String getDesc() {//          return desc;//      }////      public void setDesc(String desc) {//          this.desc = desc;//      }////      public Integer getStatus() {//          return status;//      }////      public void setStatus(Integer status) {//          this.status = status;//      }////      public Integer getCode() {//          return code;//      }////      public void setCode(Integer code) {//          this.code = code;//      }////      public Object getData() {//          return data;//      }////      public void setData(Object data) {//          this.data = data;//      }//          }}

客户端类:

package client.nio;import java.io.ByteArrayOutputStream;import java.io.ObjectOutputStream;import java.net.InetAddress;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.SocketChannel;public class Client {    public static void main(String[] args) throws Exception {        SocketChannel socketChannel = SocketChannel.open();        socketChannel.connect(new InetSocketAddress(InetAddress.getLocalHost(), 9527));//      String test1 = "hello world";        String test = "Java IO的各种流是阻塞的。这意味着,当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。 Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。 线程通常将非阻塞IO的空闲时间用于在其它通道上执行IO操作,所以一个单独的线程现在可以管理多个输入和输出通道(channel)。";        //序列化        ByteArrayOutputStream bout = new ByteArrayOutputStream();        ObjectOutputStream oout = new ObjectOutputStream(bout);        oout.writeObject(test);        //创建字节缓冲区并发送给服务端        ByteBuffer buffer = ByteBuffer.wrap(bout.toByteArray());        socketChannel.write(buffer);        socketChannel.close();    }}

测试:

启动服务器:package server.nio;public class Main {    public static void main(String[] args) {        Server server = new Server();    }}![这里写图片描述](http://img.blog.csdn.net/20161208180036256?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMjUwMTQ1OTk=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)启动客户端并发送消息:![这里写图片描述](http://img.blog.csdn.net/20161208175459426?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMjUwMTQ1OTk=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
0 0
原创粉丝点击