[英]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.