1. 程式人生 > >Java NIO框架Netty教程(十五)

Java NIO框架Netty教程(十五)

如果您持續關注OneCoder,您可能會問,在《Java NIO框架Netty教程(十四)- Netty中OIO模型(對比NIO)》中不是說下節介紹的是,NIOOIO中的worker處理方式嗎。這個一定會有的,只是在研究的過程中,OneCoder發現了之前遺留的檔案傳輸的程式碼,所以決定先完成它。

其實,Netty的樣例程式碼中也提供了檔案上傳下載的程式碼樣例,不過太過複雜,還包括了Http請求的解析等,對OneCoder來說,容易迷惑那些才是檔案傳輸的關鍵部分。所以OneCoder決定根據自己去寫一個樣例,這個理解就是在最開始提到的,Netty的傳輸是基於流的,我們把檔案流化應該就可以傳遞了。於是有了以下的程式碼:

/**
 * 檔案傳輸接收端,沒有處理檔案傳送結束關閉流的情景
 * 
 * @author lihzh
 * @alia OneCoder
 * @blog http://www.coderli.com
 */
public class FileServerHandler extends SimpleChannelHandler {

	private File file = new File("F:/2.txt");
	private FileOutputStream fos;

	public FileServerHandler() {
		try {
			if
(!file.exists()) { file.createNewFile(); } else { file.delete(); file.createNewFile(); } fos = new FileOutputStream(file); } catch (IOException e) { e.printStackTrace(); } } @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception
{ ChannelBuffer buffer = (ChannelBuffer) e.getMessage(); int length = buffer.readableBytes(); buffer.readBytes(fos, length); fos.flush(); buffer.clear(); } }
/**
 * 檔案傳送客戶端,通過位元組流來發送檔案,僅實現檔案傳輸部分,<br>
 * 沒有對檔案傳輸結束進行處理<br>
 * 應該傳送檔案傳送結束標識,供接受端關閉流。
 * 
 * @author lihzh
 * @alia OneCoder
 * @blog http://www.coderli.com
 */
public class FileClientHandler extends SimpleChannelHandler {

        // 每次處理的位元組數
	private int readLength = 8;

	@Override
	public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
			throws Exception {
		// 傳送檔案
		sendFile(e.getChannel());
	}

	private void sendFile(Channel channel) throws IOException {
		File file = new File(&quot;E:/1.txt&quot;);
		FileInputStream fis = new FileInputStream(file);
		int count = 0;
                BufferedInputStream bis = new BufferedInputStream(fis);
		for (;;) {
			byte[] bytes = new byte[readLength];
			int readNum = bis.read(bytes, 0, readLength);
			if (readNum == -1) {
				return;
			}
			sendToServer(bytes, channel, readNum);
			System.out.println(&quot;Send count: &quot; + ++count);
		}

	}

	private void sendToServer(byte[] bytes, Channel channel, int length)
			throws IOException {
		ChannelBuffer buffer = ChannelBuffers.copiedBuffer(bytes, 0, length);
		channel.write(buffer);
	}

}

待發送的檔案1.txt內容如下:

執行上述程式碼,接受到的檔案2.txt結果:

完全一模一樣。成功!

這只是一個簡單的檔案傳輸的例子,可以做為樣例借鑑。對於大檔案傳輸的情景,本樣例並不支援,會出現記憶體溢位的情景,OneCoder準備另外單獨介紹一下。