TCP消息在不确定的时间段后停止

时间:2015-04-13 08:06:18

标签: java sockets tcp tcp-ip

我有一个TCP客户端,每秒向一个只打印字符串的TCP服务器发送一个14字节的字符串。

客户端是Android应用程序,Server是在笔记本电脑上运行的简单Java应用程序。通信是从客户端到路由器的wifi,然后是以太网到笔记本电脑。

客户端连接到服务器确定并开始发送消息,但在不确定的时间后服务器停止接收消息。

查看来自服务器的wireshark流量显示服务器已确认最后一条消息但客户端显然从未收到ACK,因为它重新发送消息并且服务器发送DUP ACK。之后,在我明确关闭客户端上的socket.outputStream()之前,不会再显示任何消息,此时服务器会收到所有消息,Wireshark会显示包含所有缺失消息的TCP帧。

注意我在每条消息后都在冲洗。并且TCP_NODELAY没有效果。

  1. 为什么消息突然被缓冲?
  2. 我该怎么做才能阻止它?
  3. 注意,以下代码不适用于生产用途。这只是我可以调试它。

    客户端:

    private class SocketSender implements Runnable {
    
        private final Socket socket = new Socket();
    
        public void run() {
            Log.d(TAG, "Starting SocketSender");
            toggleButtons(SocketState.Transmitting);
            try {
                startSending();
            } catch (IOException e) {
                Log.d(TAG, "", e);
            }
            toggleButtons(SocketState.AwaitingClose);
            Log.d(TAG, "Stopping SocketSender");
        }
    
        private void startSending() throws IOException {
            int counter = 1;
            Log.d(TAG, "Opening Socket to " + HOST_ADDRESS + ":" + HOST_PORT);
            //socket.setTcpNoDelay(true);
            //socket.setPerformancePreferences(0, 1, 0);
            socket.connect(new InetSocketAddress(HOST_ADDRESS, HOST_PORT), 3000);
            Log.d(TAG, "OpenedSocket");
            try {
                final OutputStream stream = socket.getOutputStream();
                final PrintWriter output = new PrintWriter(stream);
                while (sending) {
                    final String message = "Ping pingId=" + counter;
                    output.println(message);
                    output.flush();
                    Log.d(TAG, "Sent message : " + message);
                    counter++;
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        Log.d(TAG, "Sleep interrupted", e);
                    }
                }
                output.close();
            } finally {
                //socket.close();
            }
        }
    
        private void closeSocket() {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e) {
                    Log.d(TAG, "Could not close Socket", e);
                }
            }
        }
    }
    

    服务器:

    private void readStream() throws IOException {
        final ServerSocket serverSocket = new ServerSocket(SERVER_PORT);
        final Socket socket = serverSocket.accept();
        final InputStreamReader streamReader = new InputStreamReader(socket.getInputStream());
        final BufferedReader in = new BufferedReader(streamReader);
    
        final SimpleDateFormat format = new SimpleDateFormat("YY-MM-DD HH:mm:ss.SSS");
        long lastMessage = System.currentTimeMillis();
        while (true) {
            final String inputLine = in.readLine();
            long thisMessage = System.currentTimeMillis();
            if (inputLine == null) {
                System.out.println("  No more input from : " + socket);
                break;
            }
            System.out.println(format.format(new Date(thisMessage)) + "  '" + inputLine + "' from : " + socket + "  millisSinceLastMsg=" + (thisMessage - lastMessage));
            lastMessage = thisMessage;
        }
        socket.close();
    }
    

2 个答案:

答案 0 :(得分:0)

这里的关键是发送方没有收到ACK。这是一个网络问题,而不是编码问题。令人惊讶的是,发件人没有填写其发送缓冲区,阻止,最终超时待处理的发送,并重置连接。

您可能最好在接收器上设置读取超时,并在连接时关闭连接。通过这种方式,客户端将重置连接,并且至少会知道某些错误,然后它可以重新连接或任何适当的连接。

答案 1 :(得分:0)

在测试了8个不同的接入点和11种不同的手机型号之后,这似乎只是华为Y300与某些接入点结合时的问题。

我无法确定AP导致锁定的情况,所以我决定尽可能避免使用这款手机。