StatFs类:
/**
* Retrieve overall information about the space on a filesystem. This * is a
* Wrapper for Unix statfs().
*/
检索整个文件系统的空间信息,是对Unix中statfs()函数的封装, 开发中可用这个类取得文件系统的可用大小等。
//递归取得文件或文件夹的大小 public static long fileLength(File file) { long length = 0; if(file == null || !file.exists()){ return 0; } if(file.isFile()){ length = file.length(); }else if(file.isDirectory()){ File[] files = file.listFiles(); for(int i = 0; files != null && i < files.length; i++){ length = length + fileLength(files[i]); } } return length; } //取得文件系统的可用空间 public static long availableSize(File mCurrentDirectory) { StatFs stat = new StatFs(mCurrentDirectory.getPath()); long blockSize = stat.getBlockSize(); long availableBlocks = stat.getAvailableBlocks(); long availableSize = blockSize * availableBlocks; return availableSize; }
ArrayList和HashMap是异步的,Vector和HashTable是同步的,所以Vector和HashTable是线程安全的,而 ArrayList和HashMap并不是线程安全的。因为同步需要花费机器时间,所以Vector和HashTable的执行效率要低于 ArrayList和HashMap。
客户端与服务端基于HTTP和WebSocket网络协议来通讯,其中HTTP用于从客户端向服务端的请求,WebSocket用于从服务端向客户端的推送,因此服务器端需要支持HTTP和WebSocket两种协议。HTTP好说,所有Web服务器都支持,而支持WebSocket的倒不多。
- Java阵营:Tomcat 7和Netty
- .Net阵营:System.Net.WebSockets
- Nodejs阵营:Socket.io
.Net和Nodejs俺不熟,就不作评论,Tomcat 7在最新版本里加入对Websocket支持,但我需要更为轻量级的方案,最好是内嵌,因此Netty就成了我首选。Netty源码里有websocket的Samples,我就是直接在samples上进行修改,总结下来需要如下几步:
(new Thread(new Runnable(){ @Override public void run() { ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); // Set up the event pipeline factory. bootstrap.setPipelineFactory(new WebSocketServerPipelineFactory()); int port = 8080; // Bind and start to accept incoming connections. bootstrap.bind(new InetSocketAddress(port)); System.out.println("Web socket server started at port " + port + '.'); } })).start();
public class WebSocketServerPipelineFactory implements ChannelPipelineFactory { public ChannelPipeline getPipeline() throws Exception { // Create a default pipeline implementation. ChannelPipeline pipeline = pipeline(); pipeline.addLast("decoder", new HttpRequestDecoder()); pipeline.addLast("aggregator", new HttpChunkAggregator(65536)); pipeline.addLast("encoder", new HttpResponseEncoder()); pipeline.addLast("handler", new WebSocketServerHandler()); return pipeline; } }
// Handshake WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory( this.getWebSocketLocation(req), null, false); this.handshaker = wsFactory.newHandshaker(req); if (this.handshaker == null) { wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.getChannel()); } else { this.handshaker.handshake(ctx.getChannel(), req).addListener(WebSocketServerHandshaker.HANDSHAKE_LISTENER); }如果是WebSocketFrame,则接收客户端发来的message
String request = ((TextWebSocketFrame) frame).getText();
ctx.getChannel().write(new TextWebSocketFrame("some message"));
值得注意的是目前WebSocket的实现对二进制流支持不够好,因此当需要服务端向客户端推送类似与文件类IO流时,我采取的折中方案,就是先让websocket向客户端发通知,然后再让客户端向服务端请求文件下载,当然这样的代价就是两次连接,如果有更好的方案请推荐给我。
对于HTTP,Netty从原理上说是支持的,不过支持得不够好,最新的不稳定版本才有HTTP Request的解析支持,我也没太多时间来写这块,于是乎又找了另外一个可以内嵌的Web服务器Jetty来支持HTTP和servlet,当然我用了比较老版本的Jetty 6,这个版本比较轻量,内嵌比较简单,几行代码就可以打开网络端口并支持servlet:
(new Thread(new Runnable(){ @Override public void run() { int port = 8081; Server server = new Server(port); Context root = new Context(server,"/",Context.SESSIONS); root.addServlet(new ServletHolder(new LoginSTServlet()), "/login"); try{ server.start(); System.out.println("Http server started at port " + port + '.'); }catch(Exception err){ err.printStackTrace(); } } })).start();这样,几个类就搭起了服务端,当然这只是快速开始,服务端的建设远不止这些,比如security和数据压缩等,这些我单独拿出来详细分析