简单Netty服务器未发送响应
我正在编写在TCP上运行的自定义协议搜索服务。当使用EmbeddedChannel进行测试时,一切都非常完美。为了进一步测试,我编写了一个服务器并添加了处理程序。通过来自普通java套接字客户端的请求,服务器接收数据,处理并发送回响应。但是,响应不会到达客户端套接字。我想可能是我把大管道搞砸了。因此,我将实现简化为仅一个入站处理程序。还是不行。有人能帮忙吗 服务器:简单Netty服务器未发送响应,netty,Netty,我正在编写在TCP上运行的自定义协议搜索服务。当使用EmbeddedChannel进行测试时,一切都非常完美。为了进一步测试,我编写了一个服务器并添加了处理程序。通过来自普通java套接字客户端的请求,服务器接收数据,处理并发送回响应。但是,响应不会到达客户端套接字。我想可能是我把大管道搞砸了。因此,我将实现简化为仅一个入站处理程序。还是不行。有人能帮忙吗 服务器: public void start() throws Exception{ EventLoopGroup bossGrou
public void start() throws Exception{
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
final KaiExceptionHandler kaiExceptionHandler = new KaiExceptionHandler();
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline.addLast(new SimpleHandler());
}
});
ChannelFuture future = b.bind(new InetSocketAddress("localhost", 9400)).sync();
future.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture channelFuture) throws Exception {
if(channelFuture.isSuccess()) {
LOGGER.info("Kai Server is bounded to '{}'", "localhost:9400");
}else {
LOGGER.error("Failed to bound Kai to 'localhost:9400'", channelFuture.cause());
}
}
});
future.channel().closeFuture().sync();
}finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
测试客户端。一个不整洁的实现。然而,只是为了测试
public class TestClient {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("localhost", 9400);
InputStream is = socket.getInputStream();
StringBuilder sb = new StringBuilder();
byte[] buffer = new byte[64];
int r = 0;
socket.setSoTimeout(10000);
System.out.println("Reading...");
while ((r = is.read(buffer)) != -1) {
sb.append(new String(buffer).trim());
}
System.out.println("String: " + sb.toString());
}
}您的测试程序假设在写入数据后连接会关闭,并且在发送多字节字符的情况下,其假设字符串不会断开 如果有意等待套接字关闭,则需要将
write
语句更改为以下内容:
ctx.write(unmooled.copiedBuffer(“客户端没有看到这个”,字符集))
.addListener(ChannelFutureListener.CLOSE);
然而,这种通信方式效率低下,因为每次您想对服务器说些什么时,都需要重新打开另一个套接字连接。最好的方法是将协议设置为基于行或由长度字段分隔,然后使用BufferedReader
在客户端逐行读取响应,在服务器端,您应该在每条消息的末尾添加一个新行
如果服务器需要接收消息,您应该在管道的开始处添加一个
新的LineBasedFrameDecoder()
,然后添加一个可选的新的StringDecoder()
,让netty自动将ByteBuf
转换为字符串,您不必再这样做了。Netty也可以使用StringEncoder
反向执行此操作,因此您可以只编写字符串对象,而不是每次都将其包装在ByteBuf
中查看上一个问题。整个问题都与测试客户端有关。第一个问题:
第一个由Ferrybig指出,其中
read(buffer)!=-1
要求插座关闭(感谢那位男士)。第二个问题:
第二个是,
ChannelInboundHandlerAdapter#channelRead(ChannelHandlerContext ctx,Object msg)
永远不会被调用,因为套接字不发送任何内容,所以没有任何内容可读取。编辑我的客户发送的东西,使其工作
新客户:
public class TestClient {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("localhost", 9400);
socket.setSoTimeout(10000);
OutputStream raw = socket.getOutputStream();
// Will be the request bytes
raw.write(1);
raw.flush();
InputStream is = socket.getInputStream();
StringBuilder response = new StringBuilder();
// actual expected size will be here
final int expectedResponse = 128;
byte[] buffer = new byte[expectedResponse];
int bytesRead = is.read(buffer);
if (bytesRead != -1) {
response.append(new String(buffer).trim()).append("\n");
}
System.out.println("String: " + response.toString());
}
}我明白了。”读取(缓冲区)!=-如果服务器关闭套接字,则1'为真。但是,我不想那样..协议是基于二进制的。请求和响应以二进制格式发送,固定的报头大小为17字节,可选的正文也是二进制格式。当我知道要从标题读取的确切响应正文大小时,是否需要分隔符?如果是,如何进行?
public class TestClient {
public static void main(String[] args) throws Exception {
Socket socket = new Socket("localhost", 9400);
socket.setSoTimeout(10000);
OutputStream raw = socket.getOutputStream();
// Will be the request bytes
raw.write(1);
raw.flush();
InputStream is = socket.getInputStream();
StringBuilder response = new StringBuilder();
// actual expected size will be here
final int expectedResponse = 128;
byte[] buffer = new byte[expectedResponse];
int bytesRead = is.read(buffer);
if (bytesRead != -1) {
response.append(new String(buffer).trim()).append("\n");
}
System.out.println("String: " + response.toString());
}