C ++在通过TCP发送数据之前发送数据大小

时间:2016-02-02 22:42:41

标签: c++ sockets tcp

免责声明:我对此非常陌生,所以我会尽可能地清楚。

我有一个变量"数据包"数据大小。我知道TCP是一种流媒体协议 - 它会传输字节,而不是数据包。

现在,我想告诉我的客户从流中读取的数据大小(构成我的一个数据包')。

我发送的数据是std::string格式

如果我的字符串被称为outstring,我怎么能用我需要在客户端读取的字符串大小填充UINT8 buff[4]

我的客户端,用C#编写,看起来像这样:

int total = 0;
int read;
byte[] datasize = new byte[4];

read = socket.Receive(datasize, 0, 4, 0);
int size = BitConverter.ToInt32(datasize, 0);
int dataleft = size;
byte[] data = new byte[size];

while (total < size) {
  read = socket.Receive(data, total, dataleft, 0);
  if (read == 0) {
    break;
  }
  total += read;
  dataleft -= read;
}

3 个答案:

答案 0 :(得分:3)

道歉,这不是您问题的直接答案,但可能有用。

使用原始套接字进行编程很糟糕。要使程序能够有效地处理它们,还有很多工作要做。例如,在您的代码段中,您尝试将4个字节接收到datasize中。无法保证单个socket.Receive()操作实际上会读取4个字节,它可以读取1到4个字节之间的任何内容。你必须在循环中调用socket.Receive(),直到你收到所有4个字节,就像你以后一样。

幸运的是,像ZeroMQ之类的东西几乎消除了所有的痛苦,并为你提供了一个很好的简单消息传递框架,分布在套接字,管道,内存等之上。如果你只是想得到一些事情,强烈建议。

答案 1 :(得分:1)

byte[0] = l & 0x000000ff;
byte[1] = (l & 0x0000ff00) >> 8;
byte[2] = (l & 0x00ff0000) >> 16;
byte[3] = (l & 0xff000000) >> 24;

这假设你想要它以小端格式。如果你想要bigendian

byte[3] = l & 0x000000ff;
byte[2] = (l & 0x0000ff00) >> 8;
byte[1] = (l & 0x00ff0000) >> 16;
byte[0] = (l & 0xff000000) >> 24;

答案 2 :(得分:0)

您的发送代码是用C ++编写的,所以您根本不需要字节数组,可以直接发送整数大小值,例如:

uint32_t size = htonl(outstring.size()); // convert from host byte order to network byte order (big endian)
send(theSocket, (char*)&size, sizeof(size), 0);
send(theSocket, outstring.c_str(), outstring.size(), 0);

在.NET客户端,您可以执行以下操作:

bool readSocketFully(Socket s, byte[] buf)
{
    int idx = 0;
    int dataleft = buf.Length;
    int read;

    while (dataleft > 0) {
        read = s.Receive(buf, idx, dataleft, 0);
        if (read == 0) {
            return false;
        }
        idx += read;
        dataleft -= read;
    }
    return true;
}

byte[] readPacket(Socket s)
{
    byte[] datasize = new byte[4];    

    if (!readSocketFully(s, datasize)) {
        return null;
    }

    if (BitConverter.IsLittleEndian) {
        System.Array.Reverse(datasize, 0, 4); // convert from network byte order (big endian) to host byte order (little endian)
    }
    int size = BitConverter.ToInt32(datasize, 0);
    byte[] data = new byte[size];

    if (size > 0) {
        if (!readSocketFully(socket, data)) {
            return null;
        }
    }

    return data;
}

byte[] data = readPacket(socket);
// use data as needed ...