Java套接字数据仅在发送时间延迟时有效

时间:2015-06-15 21:39:13

标签: java c++ sockets protocol-buffers

我通过原始套接字从C ++向Java发送一个protobuf,C ++程序是客户端,java程序是服务器。 C ++程序几乎每1ms生成一次数据包,然后发送到java程序。

如果我正常运行程序,我发现只有一半的数据包被接收。

如果我在C ++程序中设置断点然后运行客户端和服务器,则会收到所有数据包。

如何在不设置断点的情况下确保收到所有数据包?我可以推迟一下吗?

所有数据包的字节大小最多为15个字节。

3 个答案:

答案 0 :(得分:1)

默认情况下,TCP套接字使用“Nagle算法”,它将延迟下一个“未填充”片段的传输,以减少拥塞。您的数据包大小足够小,数据包之间的时间延迟足够小,以至于nagle算法会对您的传输产生影响。

答案 1 :(得分:1)

正如评论中已经讨论的那样,你想要做的事情不会以可靠的方式运作。这在the Protobuf documentation

中也有描述
  

如果要将多条消息写入单个文件或流,请执行此操作   由你来跟踪一条消息的结束和下一条消息的结束   开始。协议缓冲区有线格式不是自定界限的,所以   协议缓冲区解析器无法确定消息在其上的结束位置   拥有。 解决此问题的最简单方法是编写大小   在编写消息本身之前的每条消息。当你读到的时候   回来的消息,你读取大小,然后将字节读入a   单独的缓冲区,然后从该缓冲区解析。 (如果你想避免   将字节复制到单独的缓冲区,请查看CodedInputStream   class(在C ++和Java中),可以告诉它将读取限制为a   一定数量的字节。)

粗体斜体部分是您编码不正确的地方。

在写作方面你应该写

  1. Protobuf的长度采用某种格式,对于发送方和接收方都是可以理解的(在端点不同的系统之间传输时选择正确的格式尤其重要。)
  2. the protobuf
  3. 在接收端你需要

    1. 使用固定,已知长度字段的大小
    2. 执行读取
    3. 读取步骤1中学习的长度。此读取将检索protobuf。
    4. 这个问题的示例代码在这个问题上:Sending struct via Socket using JAVA and C++

答案 2 :(得分:0)

@fvu:这是我正在尝试的代码:

import Visualization.DataSetProtos.PacketData; // protos import

import java.io.InputStream;
import java.util.Arrays;
import javax.swing.JFrame;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;


class WorkerThread extends Thread {
Socket service;
static DynamicData demo;
static int size;
static int times;
static byte[] buffer;

WorkerThread(Socket service) 
{
    this.service = service;
    buffer = new byte[500];
    size = 1;
    times = 0;
}

static void Print(PacketData packetData) 
{
    System.out.print("Packet Number: " + (++times));
    System.out.print("  DataSet Size: " + packetData.getLength() + "\n");

}

static void Print(PacketHeader packetHeader) 
{
    System.out.print("Packet Number: " + (++times));
    System.out.print("  DataSet Size: " + packetHeader.getLength() + "\n");

}

public void run() {
boolean flag=true;    //you can change this flag's condition, to test if the client disconects

    if(demo == null)
    {
        demo = new DynamicData("GridMate Data Visualization");
        demo.pack();
        RefineryUtilities.centerFrameOnScreen(demo);
        //demo.setVisible(true);
    }
try
{
    while (flag)
    {

        InputStream inputStream = service.getInputStream();
        int read;
        read = inputStream.read(buffer);

        byte[] readBuffer = new byte[read];
        readBuffer = Arrays.copyOfRange(buffer, 0, read);
        PacketData packetData = PacketData.parseFrom(readBuffer);
        Print(packetData);


    }
    service.close();
}
catch(Exception e)
    {
        e.printStackTrace();
    }
}
}



public class Test
{
Test()
{
   server = null;
   client= null;
}
public static void main(final String[] args) {
    int i =0;
    try 
    {
        server = new ServerSocket(25715);

    System.out.println("Server setup and waiting for client connection ...");

            while(true)
            {
                client = server.accept();
                WorkerThread wt = new WorkerThread(client);
                wt.start();
                i++; 
           }
    }
  catch(IOException e)
  { System.out.println("IO Error in streams " + e);
    e.printStackTrace();
  }

}
 public void finalize()
 {
    try
    {
        server.close();
        client.close();
    }
    catch(Exception e)
    {
       e.printStackTrace();
    }

   }

    static ServerSocket server;
    static Socket client;
}