我有一个集成测试,可以向客户端发送800条消息。客户端可以很好地接收所有消息。问题是我的测试定期失败,因为套接字(在消息末尾),从流中不读取任何字节(-1),关闭套接字,重新打开套接字并获取字节。在读取最后一个字节之前测试“完成”(因此失败),但是我可以在日志中看到最后一条消息确实成功到达了客户端。这是断断续续的。大约每六打就会发生一次。换句话说,也许连续运行5次不会有任何错误(套接字不必关闭/重新打开),但是第六次运行会出现此问题。
到目前为止,我已经尝试提高/降低消息的发送速度。
服务器:
try
{
srvr = new ServerSocket(PORT);
Socket socket = srvr.accept();
...
OutputStream out = socket.getOutputStream();
for (String msg : Messages)
{
byte[] bytes = new BigInteger(msg, BASE_16).toByteArray();
out.write(bytes);
// Delay so client can keep up.
sleep(SOCKET_CLIENT_DELAY);
}
}
catch (IOException ioe)
{
fail(ioe.getMessage());
}
finally
{
handleClose(srvr);
}
客户:
@Override
public void run()
{
final long reconnectAttemptWaitTimeMillis = 5_000;
Socket socket = null;
while (true)
{
try
{
socket = new Socket(host, port);
boolean isConnected = socket.isConnected();
if (isConnected)
{
read(socket);
}
}
catch (ConnectException ce)
{
LOGGER.warn(
"Could not connect to ADS-B receiver/antenna on [" + host + ":" + port
+ "]. Trying again in 5 seconds...");
try
{
sleep(reconnectAttemptWaitTimeMillis);
}
catch (InterruptedException ie)
{
LOGGER.error(ie.getMessage(), ie);
break;
}
}
catch (IOException ioe)
{
LOGGER.error(ioe.getMessage(), ioe);
}
}
LOGGER.info("A total of " + totalEnqueued + " ADS-B messages were enqueued.");
}
/**
* Reads binary ADS-B messages from the {@link Socket}. Assumption is the given {@link Socket} is connected.
*
* @param socket
* where to read ADS-B messages from.
*/
private void read(final Socket socket)
{
LOGGER.info(getName() + " connected to " + host + ":" + port);
DataInputStream in = null;
try
{
in = new DataInputStream(socket.getInputStream());
while (true)
{
byte[] rawBuffer = new byte[MESSAGE_BUFFER_SIZE];
int bytesRead = in.read(rawBuffer);
if (bytesRead == -1)
{
LOGGER.warn("End of stream reached.");
break;
}
/*
* The Mode-S Beast receiver's AVR formatted output for every message begins with 0x1A.
*/
if (rawBuffer[0] == MODE_S_BEAST_PREFIX_NUM)
{
/*
* AdsbDecoder will expect a hexadecimal String representation of the ADS-B message
* without the prefix and suffix.
*
* First, we will convert the raw bytes into a hexadecimal String.
*
* Then, we will remove the Mode-S Beast metadata from the AVR format.
*
* For example:
* "1A33000000000000008DA44E325915B6B6A2FACB45988A" will look like "8DA44E325915B6B6A2FACB45988A"
*
* Finally, we enqueue the ADS-B hex message.
*/
// 1A33000000000000008DA44E325915B6B6A2FACB45988A
String modeS = new BigInteger(rawBuffer).toString(BASE_16).toUpperCase();
// Remove Mode-S Beast info
final int modesBeastPrefixLength = 18;
String adsbMessage = modeS.substring(modesBeastPrefixLength, modeS.length());
LOGGER.info("Message read from receiver/antenna: [" + adsbMessage + "]");
rawAdsbMessages.offer(adsbMessage);
++totalEnqueued;
}
}
}
catch (
IOException ioe)
{
LOGGER.error("Problem encountered reading from Socket. " + ioe.getMessage());
}
finally
{
if (Objects.nonNull(in))
{
try
{
in.close();
}
catch (IOException ex)
{
LOGGER.error("Problem encountered closing the Socket reader. " + ex.getMessage());
}
}
}
}
我希望看不到bytesRead值变为-1,并且必须重新建立连接,因为这是一项测试。我对套接字编程的了解非常有限,所以也许这是不切实际的期望。如果是这样,请告诉我原因。也许放一个缓冲的读取器/写入器。任何建议都很棒。