java NIO demo ,服务端收到文件一直没有内容,请大佬看看问题

都天星泪 发布于 05/10 03:07
阅读 104
收藏 0

package com.crazymakercircle.iodemo.socketDemos; import com.crazymakercircle.IOUtil; import com.crazymakercircle.Logger; import com.crazymakercircle.NioDemoConfig; import java.io.File; import java.io.FileInputStream; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.SocketChannel; import java.nio.charset.Charset; /** * 文件传输Client端 * */ public class NioSendClient { /** * 构造函数 * 与服务器建立连接 * * @throws Exception */ public NioSendClient() { } private Charset charset = Charset.forName("UTF-8"); /** * 向服务端传输文件 * * @throws Exception */ public void sendFile() { try { String sourcePath = NioDemoConfig.SOCKET_SEND_FILE; String srcPath = IOUtil.getResourcePath(sourcePath); Logger.debug("srcPath=" + srcPath); String destFile = NioDemoConfig.SOCKET_RECEIVE_FILE; Logger.debug("destFile=" + destFile); File file = new File(srcPath); if (!file.exists()) { Logger.debug("文件不存在"); return; } FileChannel fileChannel = new FileInputStream(file).getChannel(); SocketChannel socketChannel = SocketChannel.open(); socketChannel.socket().connect( new InetSocketAddress(NioDemoConfig.SOCKET_SERVER_IP , NioDemoConfig.SOCKET_SERVER_PORT)); socketChannel.configureBlocking(false); Logger.debug("Cliect 成功连接服务端"); while (!socketChannel.finishConnect()) { //不断的自旋、等待,或者做一些其他的事情 } //发送文件名称 ByteBuffer fileNameByteBuffer = charset.encode(destFile); socketChannel.write(fileNameByteBuffer); //发送文件长度 ByteBuffer buffer = ByteBuffer.allocate(NioDemoConfig.SEND_BUFFER_SIZE); buffer.putLong(file.length()); buffer.flip(); socketChannel.write(buffer); buffer.clear(); //发送文件内容 Logger.debug("开始传输文件"); int length = 0; long progress = 0; while ((length = fileChannel.read(buffer)) > 0) { buffer.flip(); socketChannel.write(buffer); buffer.clear(); progress += length; Logger.debug("| " + (100 * progress / file.length()) + "% |"); } if (length == -1) { IOUtil.closeQuietly(fileChannel); socketChannel.shutdownOutput(); IOUtil.closeQuietly(socketChannel); } Logger.debug("======== 文件传输成功 ========"); } catch (Exception e) { e.printStackTrace(); } } /** * 入口 * * @param args */ public static void main(String[] args) { NioSendClient client = new NioSendClient(); // 启动客户端连接 client.sendFile(); // 传输文件 } } package com.crazymakercircle.iodemo.socketDemos; import com.crazymakercircle.NioDemoConfig; import com.crazymakercircle.IOUtil; import com.crazymakercircle.Logger; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.nio.ByteBuffer; import java.nio.channels.*; import java.nio.charset.Charset; import java.util.HashMap; import java.util.Iterator; import java.util.Map; /** * 文件传输Server端 * */ public class NioReceiveServer { private Charset charset = Charset.forName("UTF-8"); /** * 服务器端保存的客户端对象,对应一个客户端文件 */ static class Client { //文件名称 String fileName; //长度 long fileLength; //开始传输的时间 long startTime; //客户端的地址 InetSocketAddress remoteAddress; //输出的文件通道 FileChannel outChannel; } private ByteBuffer buffer = ByteBuffer.allocate(NioDemoConfig.SERVER_BUFFER_SIZE); //使用Map保存每个客户端传输,当OP_READ通道可读时,根据channel找到对应的对象 Map clientMap = new HashMap(); public void startServer() throws IOException { // 1、获取Selector选择器 Selector selector = Selector.open(); // 2、获取通道 ServerSocketChannel serverChannel = ServerSocketChannel.open(); ServerSocket serverSocket = serverChannel.socket(); // 3.设置为非阻塞 serverChannel.configureBlocking(false); // 4、绑定连接 InetSocketAddress address = new InetSocketAddress(NioDemoConfig.SOCKET_SERVER_PORT); serverSocket.bind(address); // 5、将通道注册到选择器上,并注册的IO事件为:“接收新连接” serverChannel.register(selector, SelectionKey.OP_ACCEPT); System.out.println("serverChannel is linstening..."); // 6、轮询感兴趣的I/O就绪事件(选择键集合) while (selector.select() > 0) { // 7、获取选择键集合 Iterator it = selector.selectedKeys().iterator(); while (it.hasNext()) { // 8、获取单个的选择键,并处理 SelectionKey key = it.next(); // 9、判断key是具体的什么事件,是否为新连接事件 if (key.isAcceptable()) { // 10、若接受的事件是“新连接”事件,就获取客户端新连接 ServerSocketChannel server = (ServerSocketChannel) key.channel(); SocketChannel socketChannel = server.accept(); if (socketChannel == null) continue; // 11、客户端新连接,切换为非阻塞模式 socketChannel.configureBlocking(false); // 12、将客户端新连接通道注册到selector选择器上 SelectionKey selectionKey = socketChannel.register(selector, SelectionKey.OP_READ); // 余下为业务处理 Client client = new Client(); client.remoteAddress = (InetSocketAddress) socketChannel.getRemoteAddress(); clientMap.put(socketChannel, client); Logger.debug(socketChannel.getRemoteAddress() + "连接成功..."); } else if (key.isReadable()) { processData(key); } // NIO的特点只会累加,已选择的键的集合不会删除 // 如果不删除,下一次又会被select函数选中 it.remove(); } } } /** * 处理客户端传输过来的数据 */ private void processData(SelectionKey key) throws IOException { Client client = clientMap.get(key.channel()); System.out.println(client.fileName); System.out.println(client.fileLength); SocketChannel socketChannel = (SocketChannel) key.channel(); int num = 0; try { buffer.clear(); while ((num = socketChannel.read(buffer)) > 0) { buffer.flip(); System.out.println("1111====>"+new String(buffer.array(), 0, buffer.limit(), Charset.forName("utf-8"))); //客户端发送过来的,首先是文件名 if (null == client.fileName) { // 文件名 String fileName = charset.decode(buffer).toString(); String destPath = IOUtil.getResourcePath(NioDemoConfig.SOCKET_RECEIVE_PATH); File directory = new File(destPath); if (!directory.exists()) { directory.mkdir(); } client.fileName = fileName; String fullName = directory.getAbsolutePath() + File.separatorChar + fileName; Logger.debug("NIO 传输目标文件:" + fullName); File file = new File(fullName); FileChannel fileChannel = new FileOutputStream(file).getChannel(); client.outChannel = fileChannel; } //客户端发送过来的,其次是文件长度 else if (0 == client.fileLength) { // 文件长度 long fileLength = buffer.getLong(); client.fileLength = fileLength; client.startTime = System.currentTimeMillis(); Logger.debug("NIO 传输开始:"); } //客户端发送过来的,最后是文件内容 else { // 写入文件 client.outChannel.write(buffer); } buffer.clear(); } key.cancel(); } catch (IOException e) { key.cancel(); e.printStackTrace(); return; } // 调用close为-1 到达末尾 if (num == -1) { IOUtil.closeQuietly(client.outChannel); System.out.println("上传完毕"); key.cancel(); Logger.debug("文件接收成功,File Name:" + client.fileName); Logger.debug(" Size:" + IOUtil.getFormatFileSize(client.fileLength)); long endTime = System.currentTimeMillis(); Logger.debug("NIO IO 传输毫秒数:" + (endTime - client.startTime)); } } /** * 入口 * * @param args */ public static void main(String[] args) throws Exception { NioReceiveServer server = new NioReceiveServer(); server.startServer(); } } socket.server.ip=127.0.0.1 socket.server.port=18899 socket.send.file=/system.properties socket.receive.file=system.dest.properties socket.receive.path=/ send.buffer.size=1024 server.buffer.size=10240 pet.dog.class=com.crazymakercircle.otherPet.pet.LittleDog file.resource.src.path=/system.properties file.resource.dest.path=/system.copy.properties file.src.path=/testData/nio传输测试视频.mp4 file.dest.path=/testData/file.copy.nio传输测试视频.mp4

服务端收到的文件一直没有内容,这是哪里错了,请大佬指点下,实在不知道哪里问题,感谢
加载中
0
@ccny
@ccny

代码,太乱了,怎么看。

0
湖水没了
湖水没了

没有拆包得过程,文件名 文件长度 文件内容 在数据包中存在可能是连续在一个包中 也可能是在不同包中 你完全没处理

https://gitee.com/sanluan/MicroProfile  这个是我写的nio实现,有nio服务端 客户端 websocket协议客户端 服务端 文件双向同步协议 websocket容器等 代码量很小 可以看看

返回顶部
顶部