我正在尝试从服务器向客户端发送文件,即服务器请求的客户端。客户端指定中的文件FileRequestProtocol
,然后将其发送到服务器,服务器将文件大小添加到文件中,FileRequestProtocol
然后将其返回给客户端。
客户端FileChunkReqWriteHandler
向其管道添加具有正确文件大小的新文件。
服务器ChunkedFileServerHandler
使用上下文和所需文件创建一个新文件,并尝试发送该文件,但是FileChunkReqWriteHandler
从不读取该字节。
我在这里做错了什么?
记录
INFO ProtocolHeadHandler:48 - Client send ProtocolHead [version=1, jobType=FILEREQUEST]
INFO ProtocolHeadServerHandler:36 - Server receive ProtocolHead [version=1, jobType=FILEREQUEST]
INFO ProtocolHeadHandler:57 - Client ProtocolHead equals, Send Protocol FileRequestProtocol [filePath=test.jpg, fileSize=0]
INFO FileRequestServerHandler:42 - Server new FileRequest FileRequestProtocol [filePath=test.jpg, fileSize=0]
INFO FileRequestHandler:41 - Client receives FileRequestProtocol [filePath=test.jpg, fileSize=174878]
INFO ChunkedFileServerHandler:39 - New ChunkedFileServerHandler
INFO FileChunkReqWriteHandler:20 - New ChunkedFile Handler FileRequestProtocol [filePath=test.jpg, fileSize=174878]
客户
FileRequestHandler.java
public class FileRequestHandler extends
SimpleChannelInboundHandler<FileRequestProtocol> {
private Logger logger = Logger.getLogger(this.getClass());
public FileRequestHandler() {
}
@Override
public void channelRead0(ChannelHandlerContext ctx, FileRequestProtocol msg) {
logger.info("Client receives " + msg);
ReferenceCountUtil.release(msg);
ctx.channel().pipeline().addLast(new FileChunkReqWriteHandler(msg));
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
logger.info("Client read complete");
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
FileChunkReqWriteHandler.java
public class FileChunkReqWriteHandler extends SimpleChannelInboundHandler<ChunkedFile> {
FileRequestProtocol fileRequestProtocol;
private Logger logger = Logger.getLogger(this.getClass());
public FileChunkReqWriteHandler(FileRequestProtocol msg) {
this.fileRequestProtocol = msg;
logger.info("New ChunkedFile Handler " + msg);
}
@Override
public void channelActive(ChannelHandlerContext ctx) {
logger.info("in channel active method");
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
if (ctx.channel().isActive()) {
ctx.writeAndFlush("ERR: " +
cause.getClass().getSimpleName() + ": " +
cause.getMessage() + '\n').addListener(ChannelFutureListener.CLOSE);
}
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, ChunkedFile msg)
throws Exception {
logger.info("in channelRead0");
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
logger.info("channelRead");
ByteBuf buf = (ByteBuf) msg;
byte[] bytes = new byte[buf.readableBytes()];
buf.readBytes(bytes);
if(buf.readableBytes() >= this.fileRequestProtocol.getFileSize())
{
logger.info("received all data");
}
}
}
服务器
FileRequestServerHandler.java
public class FileRequestServerHandler extends
SimpleChannelInboundHandler<FileRequestProtocol> {
private File f;
private Logger logger = Logger.getLogger(this.getClass());
@Override
public void channelRead0(ChannelHandlerContext ctx, FileRequestProtocol fileRequest) {
logger.info("Server new FileRequest " + fileRequest);
f = new File(fileRequest.getFilePath());
fileRequest.setFileSize(f.length());
ctx.writeAndFlush(fileRequest);
new ChunkedFileServerHandler(ctx,f);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
logger.info("Server read complete");
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
ChunkedFileServerHandler.java
public class ChunkedFileServerHandler extends ChunkedWriteHandler {
private Logger logger = Logger.getLogger(this.getClass());
private File file;
public ChunkedFileServerHandler(ChannelHandlerContext ctx, File file) {
this.file = file;
logger.info("New ChunkedFileServerHandler");
ChunkedFile chunkedFile;
try {
chunkedFile = new ChunkedFile(this.file);
ctx.writeAndFlush(chunkedFile);
ctx.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
logger.info("FILE WRITE GETS ACTIVE");
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}
更新资料
public class ServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast("encoder", new ObjectEncoder());
p.addLast("decoder",
new ObjectDecoder(ClassResolvers.cacheDisabled(null)));
p.addLast("protocolhead", new ProtocolHeadServerHandler());
p.addLast("filerequestserverhandler", new FileRequestServerHandler());
p.addLast("chunkedfileserver", new ChunkedFileServerHandler());
}
}
服务器启动
public void startUp()
{
bossGroup = new NioEventLoopGroup(1);
workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ServerInitializer());
// Bind and start to accept incoming connections.
b.bind(this.port).sync().channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
我可以看到两个部分:
1)您不应在自己的处理程序中创建新的处理程序,而应直接创建ChunkedFile并编写它:
public class FileRequestServerHandler extends
SimpleChannelInboundHandler<FileRequestProtocol> {
private File f;
private Logger logger = Logger.getLogger(this.getClass());
@Override
public void channelRead0(ChannelHandlerContext ctx, FileRequestProtocol fileRequest) {
logger.info("Server new FileRequest " + fileRequest);
f = new File(fileRequest.getFilePath());
fileRequest.setFileSize(f.length());
ctx.writeAndFlush(fileRequest);
// directly make your chunkedFile there instead of creating a sub handler
chunkedFile = new ChunkedFile(this.file);
ctx.writeAndFlush(chunkedFile);// need a specific handler
// Don't create such an handler: new ChunkedFileServerHandler(ctx,f);
}
2)由于使用ChunkedInput(此处为ChunkedFile)编写,因此在处理程序之前必须在管道中具有ChunkedWriteHandler,因此Initializer看起来像:
public class ServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast("encoder", new ObjectEncoder());
p.addLast("decoder",
new ObjectDecoder(ClassResolvers.cacheDisabled(null)));
p.addLast("chunkedWriteHandler", new ChunkedWriteHandler());// added
p.addLast("protocolhead", new ProtocolHeadServerHandler());
p.addLast("filerequestserverhandler", new FileRequestServerHandler());
// removed: p.addLast("chunkedfileserver", new ChunkedFileServerHandler());
}
}
的位置ChunkedWriteHandler
可以更改,但始终在编写的自己的处理程序之前ChunkedFile
。
3)最后的注意事项:看一下并照顾好您的编码器/解码器(ObjectEncoder /
ObjectDecoder),因为我不确定100%是否可以与这样的从文件到文件的ByteBuf读/写协作。它可能起作用,或者不起作用…
问题内容: 我正在尝试找到一种方法,将不同文件类型的文件从服务器发送到客户端。 我在服务器上有以下代码将文件放入字节数组: 然后,我将fileData作为字符串发送给客户端。这对于txt文件效果很好,但是当涉及到图像时,我发现尽管它可以很好地创建包含数据的文件,但图像无法打开。 我不确定我是否正在按照正确的方式进行操作。谢谢您的帮助。 问题答案: 如果要读取/写入二进制数据,则应使用字节流(Inp
问题内容: 由于我是Web服务的新手,请您告诉我问题的答案。我的问题是 我想实现一个Web服务,当客户端调用此Web服务时,该服务会向客户端发送pdf文件。 请有人帮我提供一段不错的代码或解释。 现在可以请一个人解决我的错误。 12-23 09:42:48.429:调试/安装(32):DexInv:-开始’/data/app/vmdl33143.tmp’— 12-23 09:42:51.708:调
我正在创建我的产品,并与这个问题。有一天,我设置了Socket.io,一切都很好。第二天,我将服务器和客户端从http迁移到HTTPS。迁移后客户端和服务器端仍然连接,但不能从客户端发射到服务器,从服务器发射到客户端。 我的ssl证书位于和中,它们加载正确。运行在上的服务器 我的示例react组件。我的react应用程序运行在上。HTTPS连接良好,工作良好。 我该怎么办?也许我在中错误地使用了s
我试图实现一个tcp客户端,它将使用spring Integration连接到现有的服务器。对于这项技术还是新手,我已经在https://github.com/spring-projects/spring-integration-samples上学习了spring示例。 主要方法: 如何强制此客户端连接到我的服务器,即使我不想发送数据?
我试图从客户端复制文件到服务器,在Java,像这样: 客户: 服务器: 当我跑步时,我得到: 但什么都没发生。这是我第一次使用客户机服务器,我不确定自己出了什么问题。 请帮帮忙。谢谢你。
问题内容: 首先,我将请求的文件从服务器发送到客户端,然后再将文件的计算出的sha从服务器发送到客户端,以便客户端可以检查发送文件和接收文件中的sha是相同的。 我设法发送了文件,但是当我尝试也发送sha(这是一个变量)时,我收到一个错误消息(我相信sha也已添加到文件内容中) 如何分别发送? 和客户: 问题答案: 您应该重新设计应用程序的工作方式: 首先,服务器将文件大小发送给客户端 客户端读取