从输入流读取数据而无需客户端“flush()”

时间:2012-01-31 17:43:29

标签: java sockets tcp inputstream flush

我已经实现了一个Java程序,它通过ServerSocket从GPS设备读取数据。

ServerSocket serverSocket = new ServerSocket(13811);
serverSocket.setReceiveBufferSize(receiveBufferSize);
Socket incomingSocket = serverSocket.accept();
InputStream stream = incomingSocket.getInputStream();
byte[] buffer = new byte[1000];
            StringBuffer sb = new StringBuffer();
System.out.println("START getting message from TCP stream: " + dateFormat.format(Calendar.getInstance().getTime()));

            while (stream.read(buffer) > 0)
            {
                sb.append(new String(buffer));
                System.out.println(sb.toString());
            }
System.out.println("[incomingMessage]: " + incomingMessage);

System.out.println("FINISHED getting message from TCP stream: " + dateFormat.format(Calendar.getInstance().getTime()));

然而,我们发现存在大的延迟(即Sys out“START ...”和“FINISHED ...”时间之间的大偏差)。花在inputStream.read()上的时间。

如果我使用Java客户端连接到上述服务器端口并向其发送数据,则服务器的inputStream可在几毫秒内读取该消息。下面显示了Java客户端代码。

Socket socket = new Socket("localhost", 13811); 
DataOutputStream out = new DataOutputStream(new  BufferedOutputStream(socket.getOutputStream()));
String tobesend = "testing message 1";
out.writeBytes(tobesend);
out.flush();
out.close();

但是,如果我在“out.flush()”和“out.close()”之前添加“Thread.Sleep(10 * 1000)”,服务器端的延迟将变为10秒...因此我怀疑如果GPS设备没有执行“刷新”并导致服务器端inputstream.read()的延迟......

不幸的是,我们无法控制GPS设备TCP呼叫,因此我无法对其进行任何修改以强制它将“刷新”消息发送到我的输入流...请提示是否有任何方法服务器端可以即使客户端(即GPS设备)没有执行“刷新”,从输入流读取数据也没有这样的延迟?

2 个答案:

答案 0 :(得分:6)

接收方无法读取尚未发送的数据。它不能强制另一端发送尚未发送的数据。

答案 1 :(得分:0)

感谢Peter Lawrey的建议,我们使用TCPDump证明数据在建立连接后几秒钟就被刷新到我们的服务器。这就是服务器程序捕获大量延迟的原因。

然后,我们使用相同的服务器程序执行一些负载测试,通过4000个测试GPS设备每隔5分钟向其推送数据,每个数据大约为300字节。

我们尝试通过引入Threadpool来处理TCP数据检索来修改服务器代码,并希望这会给我们带来更好的性能。

我们打开了TCPDump,发现这次在TCPDump时间戳和Java程序中捕获的“START ...”时间戳之间发现了时间偏差。偏差大约是几秒到不到20秒......

有关如何解决问题的任何建议吗?

Threadpool的初始化:

blockingQueueForRetriveTCPMsg = new LinkedBlockingQueue<Runnable>(50);
threadPoolExecutorForRetriveTCPMsg = new ThreadPoolExecutor(
    50,1200, 0, TimeUnit.SECONDS,
    blockingQueueForRetriveTCPMsg, 
    new ThreadPoolExecutor.CallerRunsPolicy());

ServerSocket.accept():

ServerSocket serverSocket = new ServerSocket(13811);
serverSocket.setReceiveBufferSize(receiveBufferSize);
Socket incomingSocket = serverSocket.accept();

RetrieveTcpMessage retrieveTcpMessage = new RetrieveTcpMessage(incomingSocket);
Thread retrieveTcpMessageThread = new Thread(retrieveTcpMessage);
threadPoolExecutorForRetriveTCPMsg.execute(retrieveTcpMessageThread);

Inside RetrieveTcpMessage.run(),simuilar to before:

InputStream stream = incomingSocket.getInputStream();
byte[] buffer = new byte[1000];
        StringBuffer sb = new StringBuffer();
System.out.println("START getting message from TCP stream: " +     dateFormat.format(Calendar.getInstance().getTime()));

        while (stream.read(buffer) > 0)
        {
            sb.append(new String(buffer));
            System.out.println(sb.toString());
        }
System.out.println("[incomingMessage]: " + incomingMessage);

System.out.println("FINISHED getting message from TCP stream: " +  dateFormat.format(Calendar.getInstance().getTime()));