gpt4 book ai didi

java - Android(Java) 从 Netty Nio 服务器读取时套接字读取挂起

转载 作者:太空宇宙 更新时间:2023-11-04 14:46:57 25 4
gpt4 key购买 nike

我已经实现了一个带有如下管道的 Netty 服务器:

 public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
p.addLast(new ByteArrayDecoder(), new Byte2MsgHandler()
, new ByteArrayEncoder(), new Msg2ByteHandler(), new MsgDispatcher());
}

业务逻辑在MsgDispatcher()中。见下文:

public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
super.channelRead(ctx, msg);
Msg message = (Msg) msg;
switch (message.messageType) {
case MType.SIGN_UP://sends response to the client
if (userValidator.validate(message.user)) {
userReg.signUp(message.user);
} else {
Msg error = new Msg.Builder().messageType(MType.ERROR)
.errorCode(Constants.USERREG_NULL).build();
ctx.write(error.toByteArray());// write the response back
ctx.flush(); //flush the stream
}
break;
}
}

我可以使用以下 Android 代码成功将数据发送到服务器:

public void writeAndFlush(Msg msg) throws IOException {
try {
bos.write(msg.toByteArray());
bos.flush();
} catch (IOException e) {
throw new IOException("Exception writing and flushing Msg to network.", e);
}
}

bos 是来自套接字的 bufferedOutputstream。

当我在写入后关闭服务器套接字时,我可以成功读取数据。

Msg error = new Msg.Builder().messageType(MType.ERROR)
.errorCode(Constants.USERREG_NULL).build();
ctx.write(error.toByteArray());// write the response back
ctx.flush(); //flush the stream
ctx.close(); //this result in sucessfull read on android socket.

但是(上面的服务器代码中没有“ctx.close()”),它卡在 while 循环中(下面的代码):

public Msg read() throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int read = 0;
try {
while ((read = bis.read(buffer, 0, buffer.length)) != -1) {
Log.e("com.traderreg", "" + read);
baos.write(buffer, 0, read);
}
baos.flush();
} catch (IOException e) {
throw new IOException("error reading bytes from socket", e);
}
try {
return wire.parseFrom(baos.toByteArray(), Msg.class);
}catch (IOException e){
throw new IOException("error parsing Msg from socket", e);
}
}

有什么问题吗?

最佳答案

bis.read() 将阻塞,直到有可用字节或关闭流。这就是为什么关闭套接字会导致 read() 返回。如果您想以非阻塞方式读取,那么您需要查看 java.nio.channels 包中的类。但是,您并不真的希望连续轮询数据。 java.nio.channels 中的类实际上是为在单个线程中处理多个套接字而设计的,而不是鼓励轮询套接字(尽管我知道游戏有时会轮询套接字作为游戏循环的一部分)。

无论您使用的是阻塞 I/O 还是非阻塞 I/O,您都需要某种方法来分隔消息。建议在每条消息前面添加长度字段,这是一个简单但有效的解决方案。然后,您的线程循环不断地读取消息并将它们分派(dispatch)给可以处理它们的代码。

关于java - Android(Java) 从 Netty Nio 服务器读取时套接字读取挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24294442/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com