在较高的层面上,我们使用 TCP 在网络上的两个客户端之间进行通信。客户使用不同的语言。
我们的消息传递工作流程如下:
C ++启动一个命令 Java读取命令 Java做了一些简单的逻辑 Java回应
我们已经开始看到越来越多的差异与C ++代码发送的内容以及Java代码所接收的内容有关。 为了追踪此错误,我们已经放置了多个日志记录语句和 Wireshark 配置文件,以尝试捕获尽可能多的数据来跟踪消息。
C ++日志显示该命令被发送为“123,abc,def,456”
调试C ++显示字符的字节顺序与此匹配,因为正在触发写入套接字的命令。
Wireshark将消息显示为“123,abc,def,456”
Java从套接字读取,并显示消息混乱。我们收到了以下消息:
“123,abc,def,456”(正确)
“BC,DEF,456”(截断)
“1a2,3bdfec,4,56”(完全受损)
C ++代码示例
while ( Client->Connected && !bolExitNow){
data =S"";
Threading::Thread::Sleep(15);
bolReadStream = !bolReadStream;
if (!(bolReadStream && stream->DataAvailable )){
if (sharedInfo->CutSocketClientPort == RemotePort){
if (lbSocketMessages->read(&data)){ //the read() assigns stuff to data so that it's not an empty string anymore
bytes1 = Text::Encoding::ASCII->GetBytes( data);
stream->Write( bytes1, 0, bytes1->Length );
if (sharedInfo->curAcknowledgeItem->SendMessageType->CompareTo(data->Substring(7,2)) == 0){
sharedInfo->LastXXMsgTime = DateTime::Now ;
}
}
lbSocketMessages->acknowledge();
sharedInfo->WriteLog ( String::Format("{0} Sent msg: {1}",System::DateTime::Now.ToString("yyyyMMddHHmmss.fff"),data));//log write; This shows correct format message
}
}
continue;
}
java代码示例
/** Shared read buffer. */
ConcurrentLinkedQueue<String> buffer = new ConcurrentLinkedQueue<String>();
//Instantiation
Socket client;
try{
client = new Socket(serverAddress, serverPort);
sock[thread] = new SocketMagic(client);
sock[thread].setMonitoring(false);
sock[thread].setHeartbeat("");
} catch (Exception e){
e.printStackTrace();
}
//Usage
while (!done){
if (socket[thread] != null && socket[thread].isAlive()){
message = socket[thread].getLine(MAX_DELAY_INTERVAL);
if(message!=null){
logger.log("RECEIVING ON {" + thread + "}: " + message);//displays incorrect message data
buffer.add(message);//Buffer for processing messages
}
}
//...
//logic
//...
if (buffer != null){
message = buffer.poll();
if (message != null){
response = processMessage(message,thread);//obviously wrong, as we read in incorrect information above.
}
}
}
SocketMagic库getline方法列为
public String getLine()
{
return getLine(true, 0);//Always enable blocking
}
public String getLine(final boolean blocking, final int maxwait)
{
// to block, or not to block (while waiting for data)
StringBuilder buffer = new StringBuilder();
int character;
boolean messageStarted = false;
try
{
if (blocking)
{
int wait = 0;
while (maxwait <= 0 || wait < maxwait)
{
while (sockIn.ready())
{
character = sockIn.read();
if (character == STX)
{
if (!messageStarted)
{ // if no message started
messageStarted = true; // start a message
} else
{
buffer.setLength(0); // clear message buffer
}
continue; // don't add STX to buffer
}
// ignore characters prior to message start
if (!messageStarted)
{
continue;
}
// if not end of message, keep reading
if (character != ETX)
{
// append to buffer
buffer.append((char) character);
continue;
}
// if the message is a heartbeat, keep reading
if (buffer.toString().equals(heartbeat))
{
buffer.setLength(0); // clear buffer
messageStarted = false;
continue;
}
// we've got a complete message, return it
return buffer.toString();
}
// sleep loop to avoid CPU wasting
try
{
wait += SLEEPSTEP;
Thread.sleep(SLEEPSTEP);
if (monitor && (wait % (HEARTBEATINTERVAL)) == 0)
{
if (!sockOut.write(heartbeat))
{
return null;
}
}
} catch (InterruptedException ie)
{
return null;
}
} // ENDOF while ( !sock_in.ready() )
} // ENDOF if (blocking)
// set mark, if supported (which it should be)
if (sockIn.markSupported())
{
sockIn.mark(READAHEADSIZE);
}
while (sockIn.ready())
{
character = sockIn.read();
if (character == STX)
{
if (!messageStarted)
{ // if no message started
messageStarted = true; // start a message
} else
{
buffer.setLength(0); // clear message buffer
}
continue; // don't add STX to buffer
}
// ignore characters prior to message start
if (!messageStarted)
{
continue;
}
// if not end of message, keep reading
if (character != ETX)
{
buffer.append((char) character); // add char to buffer
continue;
}
// if we read a heartbeat message, keep reading
if (buffer.toString().equals(heartbeat))
{
// System.out.println("DEBUG: HEARTBEAT");
buffer.setLength(0);
messageStarted = false;
// set new mark position for input stream
if (sockIn.markSupported())
{
sockIn.mark(READAHEADSIZE);
}
continue;
}
// we've got a complete message, mission accomplished!
// return buffer.substring(1, buffer.length() - 1);
return buffer.toString();
} // ENDOF while (sockIn.ready())
// incomplete message, reset the mark, if supported
if (sockIn.markSupported())
{
sockIn.reset();
}
return null; // no message or incomplete message
} catch (IOException ioe)
{
return null;
}
} // ENDOF public String getLine(boolean blocking, int maxwait)