采用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
- 采用Java nio 实现的一个简单的服务器
- 一个基于java NIO的Http服务器
- 一个简单web服务器的java实现
- Java 实现一个简单的web服务器
- java实现一个简单的Web服务器
- java实现一个简单的Web服务器
- Java实现一个简单的Web服务器
- 一个简单的Java web服务器实现
- 一个java实现的简单日历,采用左树右列表的方式实现,具有参考意义
- 一个简单的Java服务器
- java 简单的文件上传下载服务器模型(NIO 版本)
- java nio http服务器(3)简单的Servlet容器
- 使用Java Nio异步套接字实现一个简单的http代理服务器
- 一个简单的NIO实例
- 采用KNN算法实现一个简单的推荐系统
- Java NIO编写Socket服务器的一个例子
- Java NIO编写Socket服务器的一个例子
- 用Java实现一个简单的服务器与客户端程序
- EA策略:BOLL通道区间取BAR的指标
- nor flash启动与nand flash启动的区别
- 大型网站架构体系的演变(下)
- 微信页面基础
- Unity 游戏框架搭建 (八) 减少加班利器-QLog
- 采用Java nio 实现的一个简单的服务器
- java Excel导入导出,基于XML的实现,easy-excel使用
- CAGradientLayer的使用
- 二维数组查找某数
- Android Gradle Build Error:Some file crunching failed, see logs for details解决办法(转载)
- [真格邦]Java学习开篇
- SSL P1624 小萨的烦恼
- Java之IO流学习总结-上
- Java之IO流学习总结-下