部分收据从接口C的数据包++(Partial receipt of packets from soc

2019-09-17 12:54发布

我有一个麻烦,我的服务器应用程序发送数据包的8个字节长度- AABBCC1122334455但我的应用程序接收这个数据包两个部分AABBCC1122334455 ,通过“接收”功能,我怎么能解决呢?

谢谢!

Answer 1:

综上所述一个liitle位:

  1. TCP连接不上的应用程序级的数据包或消息,你处理的字节流进行操作。 从这个角度来看它类似于从文件中写入和读出。
  2. 无论sendrecv可以发送和接收比参数提供的数据较少。 你必须正确地处理它(通常是通过运用恰当的环路待命)。
  3. 当你正在处理的数据流,你必须要找到将其转换为有意义的数据在应用程序的方式。 换句话说,你要设计系列化协议

从您已经提到的,你很可能要发送某种信息(当然,它通常是什么人做)的。 关键是正确地发现消息的边界。 如果你的消息是固定的大小,只需从数据流中获取数据的相同数量和它翻译成你的消息; 否则,你需要一个不同的方法:

  • 如果你能拿出不能在你的信息存在的人物,也可能是您的分隔符。 然后,您可以读取流,直到到达角色,这将是你的消息。 如果传输ASCII字符(串),可以使用零作为分隔符。

  • 如果您传输二进制数据(原始整数等),所有的字符可以出现在你的信息,所以没有什么可以作为分隔符行事。 也许在这种情况下,最常见的方法是使用含有邮件的大小固定大小的前缀。 这种额外的场大小取决于消息的最大尺寸(你很可能是4个字节安全的,但如果你知道什么是最大尺寸,你可以用较低的值)。 然后,你的包看起来像SSSS|PPPPPPPPP... (字节流),其中S是额外的大小字段和P是你的有效载荷(在应用程序的实际消息,数P字节,由价值决定S )。 你知道,每包有4个特殊字节(开始S字节),这样你就可以作为一个32位整数阅读。 一旦你知道封装消息的大小,你看所有的P字节。 你与一个包完成后,您就可以读取插座一个又一个。

好消息,虽然,你可以拿出一些完全不同的。 所有你需要知道的是如何从字节流,以及如何deserialise邮件send / recv行为方式。 祝好运!

编辑:

的函数实施例接收的字节任意数量成阵列:

bool recv_full(int sock, char *buffer, size_t size)
{
  size_t received = 0;
  while (received < size)
  {
    ssize_t r = recv(sock, buffer + received, size - received, 0);
    if (r <= 0) break;
    received += r;
  }

  return received == size;
}

和实施例中接收分组具有2字节的前缀限定的有效载荷的大小的(有效载荷大小,然后限于65KB):

uint16_t msgSize = 0;
char msg[0xffff];

if (recv_full(sock, reinterpret_cast<char *>(&msgSize), sizeof(msgSize)) &&
    recv_full(sock, msg, msgSize))
{
  // Got the message in msg array
}
else
{
  // Something bad happened to the connection
}


Answer 2:

这是多么recv()适用于大多数平台。 你必须检查你收到的字节数,并继续称其为一个循环,直到你得到你所需要的数量。



Answer 3:

你“修理”,通过在一个循环 ,直到你得到足够的字节是有意义的应用程序从TCP套接字读取。



Answer 4:

我的服务器应用程序发送数据包的8个字节长度

并不是的。 你的服务器发送8个单个字节,8个字节长不是一个包。 TCP数据发送在字节流,而不是一个数据包流。 TCP既不尊重也不是任何维持“数据包”的边界,你可能有一点。

如果你知道你的数据在N个字节的量子提供,然后调用recv在一个循环:

std::vector<char> read_packet(int N) {
  std::vector buffer(N); 
  int total = 0, count;
  while ( total < N && (count = recv(sock_fd, &buffer[N], N-total, 0)) > 0 )
    total  += count;
  return buffer;
}

    std::vector<char> packet = read_packet(8);

如果你的包是变长,尝试数据本身前发送的:

int read_int() {
  std::vector<char> buffer = read_packet(sizeof (int));
  int result;
  memcpy((void*)&result, (void*)&buffer[0], sizeof(int));
  return result;
}

  int length = read_int();
  std::vector<char> data = read_buffer(length); 


文章来源: Partial receipt of packets from socket C++