[英]Java SocketChannel Read Entire String
在我当前的项目中,我试图将字符串从一台计算机传输到另一台计算机,并且在从大量示例中找到并学习之后,我设法获得了一种基本的通信形式。
我遇到的问题是,如果一台计算机尝试发送太长的消息,它似乎被分解成多个部分(大约3700个字符),并且我的解析方法失败。
我正在使用选择器来遍历所有通道。 以下是相关代码:
if(key.isReadable()) {
// Get the channel and read in the data
SocketChannel keyChannel = (SocketChannel)key.channel();
ByteBuffer buffer = buffers.get(keyChannel);
int length = 0;
try {
length = keyChannel.read(buffer);
} catch ( IOException ioe) {
closeChannel(keyChannel);
}
if(length > 0) {
buffer.flip();
// Gather the entire message before processing
while( buffer.remaining() > 0) {
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
fireReceiveEvent(keyChannel, data);//Send the data for processing
}
buffer.compact();
} else if (length < 0) {
closeChannel(keyChannel);
}
}
如何保证在传递消息之前立即读取整个消息(无论长度如何)?
与许多比我了解更多的人交谈之后。 问题的根源在于,使用TCP不可能知道整个“消息”何时到达,因为没有消息之类的消息,因为TCP在双向字节流上工作。 解决方案是创建您自己的协议并实现您自己的“消息”定义。
对于我的项目,每条消息都以[
或{
开头,并以]
或}
结尾,具体取决于起始字符。 我搜索接收到的数据,如果有完整的消息,则抓取并将其传递给处理程序。 否则,请跳过频道,然后等待更多内容到达。
这是处理消息接收的代码的最终版本。
if(key.isReadable()) {
// Get the channel and read in the data
SocketChannel keyChannel = (SocketChannel)key.channel();
ByteBuffer buffer = buffers.get(keyChannel);
int length = 0;
try {
length = keyChannel.read(buffer);
} catch ( IOException ioe) {
key.cancel();
closeChannel(keyChannel);
}
if (length > 0) {
buffer.flip();
// Gather the entire message before processing
if (buffer.remaining() > 0) {
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
buffer.rewind();
int index = 0;
int i = 0;
// Check for the beginning of a packet
//[ = 91
//] = 93
//{ = 123
//} = 125
if (data[0] == 91 || data[0] == 123) {
// The string we are looking for
byte targetByte = (byte) (data[0] + 2);
for (byte b : data) {
i += 1;
if (b == targetByte) {
index = i;
break;
}
}
if (index > 0) {
data = new byte[index];
buffer.get(data, 0, index);
fireReceiveEvent(keyChannel, data);
}
} else {
for (byte b : data) {
i += 1;
if (b == 91 || b == 123) {
index = i;
break;
}
}
if (index > 0) {
data = new byte[index];
buffer.get(data, 0, index); // Drain the data that we don't want
}
}
}
buffer.compact();
} else if (length < 0) {
key.cancel();
closeChannel(keyChannel);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.