套接字会话终止符

时间:2011-04-15 16:23:25

标签: sockets

在套接字中读取数据时,重要的是保留message terminator symbo l或在信息的标记处添加Packet size information

如果使用终结符号并发送二进制消息,则无法保证终结符号不会出现在消息的中间(除非使用某些特殊编码)。

另一方面,如果附上尺寸信息。大小信息是无符号的,如果使用一个字节,它不能用于传输长度超过256字节的消息。如果使用4字节整数。它甚至不能保证4个字节将成为一个整体。可以假设大小信息已经到达,只有2个字节的大小信息可以使用该2个字节,其余的整数数据将被丢弃。如果缓冲区上只有3个字节可用,则等待4个字节在读缓冲区上可用会导致无限期等待(例如,如果总缓冲区为7个字节或4077个字节长)。

这里有两种可能的方法

  1. sizeInfo分隔符块
      

    读取直到找到分隔符,一旦发现读取,直到sizeInfo字节通过

  2.   
  3. 在收到sizeInfo后,在unreadyBytes初始化4并相应地更改
  4.   

    这两个中哪一个更安全?请批评

    修改

    我的核心问题是如何确保大小字节已正确到达。假设消息的大小可变。

1 个答案:

答案 0 :(得分:1)

  

它甚至不能保证4个字节将成为一个整体。可以假设大小信息已经到达,只有2个字节的大小信息可以使用该2个字节,其余的整数数据将被丢弃。如果缓冲区上只有3个字节可用,则等待4个字节在读缓冲区上可用会导致无限期等待(例如,如果总缓冲区为7个字节或4077个字节长)。

如果你有一个4字节长度的描述符,你应该总是读取至少4个字节,因为发送者应该在服务器接收的每条消息中写入这个字节。如果你不能得到它们,也许在传输方面存在问题。我真的无法理解你的问题。

无论如何,我建议你不要使用任何分隔块。 在您正在传输的数据块上放置标题,并使用缓冲区重建数据包流。

您必须至少读取数据包的标头以确定其长度。

您可以为数据包定义基本结构:

struct packet{
     uint32 id;
     char payload[MAX_PAYLOAD_SIZE];
};

您从套接字读取数据,将它们存储到缓冲区中:

struct packet buffer;

然后你可以从套接字读取数据:     int n;     n =读取(newsocket,& buffer,sizeof(uint32)+ MAX_PAYLOAD_SIZE);

read返回读取的字节数。如果您准确读取发件人的数据包,则n = id。否则,您可能会阅读更多数据(例如发件人发送给您的更多数据包)。如果您正在接收拆分为单元的数据流(由数据包结构表示),那么您可以使用数据包数组来存储收到的完整数据包,并使用临时缓冲区来管理传入的数据包。 类似的东西:

struct packet buffer [MAX_PACKET_STORED];    char temp_buffer [MAX_PAYLOAD_SIZE + 4];

int n;    n =读取(newsocket,& buffer,sizeof(uint32)+ MAX_PAYLOAD_SIZE);

//这里假设已收到100字节有效载荷+ 32位长度+ 100字节的数据包    //下一个数据包的片段。    //然后:

int first_pack_len, second_pack_len;

first_pack_len = *((uint32 *)&temp_buffer[0]); //retrieve packet length

memcpy(&packet_buffer[0], temp_buffer, first_pack_len + sizeof(uint32)) //store the first packet into the array

second_pack_data_available_in_buffer = n - (first_pack_len + sizeof(uint32)); //total bytes read minus length of the first packet read
second_pack_len = *((int *)&temp_buffer[first_pack_len + sizeof(uint32)]);

我希望已经足够清楚了。但也许我误解了你的问题。 还要注意,如果2个终端系统通信可以有不同的endiannes,那么在发送/接收长度值时,最好在长度上使用htonl / ntohl函数。但这是另一个问题)