Java NIO框架Netty教程(十五)
阿新 • • 發佈:2018-12-23
如果您持續關注OneCoder,您可能會問,在《Java NIO框架Netty教程(十四)- Netty中OIO模型(對比NIO)》中不是說下節介紹的是,NIO和OIO中的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("E:/1.txt");
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("Send count: " + ++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準備另外單獨介紹一下。