我有一个socketChannel配置为阻塞,但是当从这个套接字读取5K的字节缓冲区时,我有时会得到一个不完整的缓冲区。
ByteBuffer messageBody = ByteBuffer.allocate(5*1024);
messageBody.mark();
messageBody.order(ByteOrder.BIG_ENDIAN);
int msgByteCount = channel.read(messageBody);
偶尔,messageBody没有完全填充,并且channel.read()不返回-1或异常,而是读取的实际字节数(小于5k)。
有没有人遇到过类似的问题?
答案 0 :(得分:4)
这就是读取工作的方式。 SocketChannel文档说:
读操作可能无法填充缓冲区,实际上它根本不会读取任何字节。 [...]但是,保证如果通道处于阻塞模式且缓冲区中至少有一个字节,则此方法将阻塞直到至少读取一个字节 [强调补充]。
答案 1 :(得分:1)
使用套接字时,必须预期套接字可能传输的字节数少于预期。您必须循环.read方法以获取剩余的字节。
通过套接字发送字节时也是如此。您必须检查已发送的字节数,并在发送时循环,直到所有字节都已发送。
此行为是由于网络层将邮件拆分为多个数据包。如果您的消息很短,那么您就不太可能遇到此消息。但是你应该总是为它编码。
每个缓冲区有5k字节,您很可能会看到发送方的消息吐出多个数据包。每次读取操作都将收到一个数据包,这只是您信息的一部分。
答案 2 :(得分:0)
TCP / IP以数据包形式发送信息,当您执行读取时它们并不总是可用,因此您必须循环读取。
char [] buffer = new char[1024];
int chars_read;
try
{
while((chars_read = from_server.read(buffer)) != -1)
{
to_user.write(buffer,0,chars_read);
to_user.flush();
}
}
catch(IOException e)
{
to_user.println(e);
}