Java套接字间歇性读取数据失败

时间:2019-04-12 17:24:40

标签: java sockets inputstream datainputstream

我有一个集成测试,可以向客户端发送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,并且必须重新建立连接,因为这是一项测试。我对套接字编程的了解非常有限,所以也许这是不切实际的期望。如果是这样,请告诉我原因。也许放一个缓冲的读取器/写入器。任何建议都很棒。

0 个答案:

没有答案