ENET(五)--enet_peer_send()函数

这个函数用于ENET发送数据前的准备,将数据及相关参数都打包加入待发送队列中。peer为对端,packet为待发送的数据包
int                   
enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet)
{                     
   ENetChannel * channel = & peer -> channels [channelID];
   ENetProtocol command;
   size_t fragmentLength;

   if (peer -> state != ENET_PEER_STATE_CONNECTED ||
       channelID >= peer -> channelCount ||
       packet -> dataLength > peer -> host -> maximumPacketSize)
     return -1;       

   //mtu=1400, header为4字节,Fragment为24字节,因此,fragment为1372
   fragmentLength = peer -> mtu - sizeof (ENetProtocolHeader) - sizeof (ENetProtocolSendFragment);
   if (peer -> host -> checksum != NULL)
     fragmentLength -= sizeof(enet_uint32);

   //这个语句是当所要传输的包大小大于fragmentLength(1372)时,就分块发送,每块1372,这里可以在调用该函数时,每次读取的包小于1372,则该部分可以跳过;由于包太大传输不稳定,太小了效率低,因此对包大小需要稍作权衡。
   if (packet -> dataLength > fragmentLength)
   {                  
      enet_uint32 fragmentCount = (packet -> dataLength + fragmentLength - 1) / fragmentLength,
             fragmentNumber,
             fragmentOffset;
      enet_uint8 commandNumber;
      enet_uint16 startSequenceNumber; 
      ENetList fragments;
      ENetOutgoingCommand * fragment; **//该值为待发送的数据,包括packet包、时间、指令、序号等。**

      if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT)
        return -1;    

      if ((packet -> flags & (ENET_PACKET_FLAG_RELIABLE | ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT)) == ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT &&
          channel -> outgoingUnreliableSequenceNumber < 0xFFFF)
      {               
         commandNumber = ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT;
         startSequenceNumber = ENET_HOST_TO_NET_16 (channel -> outgoingUnreliableSequenceNumber + 1);
      }        
       else            
      {               
         commandNumber = ENET_PROTOCOL_COMMAND_SEND_FRAGMENT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
         startSequenceNumber = ENET_HOST_TO_NET_16 (channel -> outgoingReliableSequenceNumber + 1);
      }               

      enet_list_clear (& fragments);
      //for循环发送
      for (fragmentNumber = 0,
             fragmentOffset = 0;
           fragmentOffset < packet -> dataLength;
           ++ fragmentNumber,
             fragmentOffset += fragmentLength)
      {               
         if (packet -> dataLength - fragmentOffset < fragmentLength)
           fragmentLength = packet -> dataLength - fragmentOffset;

         fragment = (ENetOutgoingCommand *) enet_malloc (sizeof (ENetOutgoingCommand));
         if (fragment == NULL)
         {            
            while (! enet_list_empty (& fragments))
            {         
               fragment = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (& fragments));

               enet_free (fragment);
            }         

            return -1;
         }            
         //给发送数据结构体赋值
         fragment -> fragmentOffset = fragmentOffset;
         fragment -> fragmentLength = fragmentLength;
         fragment -> packet = packet;
         fragment -> command.header.command = commandNumber;
         fragment -> command.header.channelID = channelID;
         fragment -> command.sendFragment.startSequenceNumber = startSequenceNumber;
         fragment -> command.sendFragment.dataLength = ENET_HOST_TO_NET_16 (fragmentLength);
         fragment -> command.sendFragment.fragmentCount = ENET_HOST_TO_NET_32 (fragmentCount);
         fragment -> command.sendFragment.fragmentNumber = ENET_HOST_TO_NET_32 (fragmentNumber);
         fragment -> command.sendFragment.totalLength = ENET_HOST_TO_NET_32 (packet -> dataLength);
         fragment -> command.sendFragment.fragmentOffset = ENET_NET_TO_HOST_32 (fragmentOffset);         
            enet_list_insert (enet_list_end (& fragments), fragment);
      }               

      packet -> referenceCount += fragmentNumber;

      while (! enet_list_empty (& fragments))
      {               
         fragment = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (& fragments));  //发送后要将队列中的数据删除,fragment指向下一个数据
         //将分包加入待发送队列。   
         enet_peer_setup_outgoing_command (peer, fragment);
      }               

      return 0;       
   } //包太大时分包发送结束。  

   command.header.channelID = channelID;

   if ((packet -> flags & (ENET_PACKET_FLAG_RELIABLE | ENET_PACKET_FLAG_UNSEQUENCED)) == ENET_PACKET_FLAG_UNSEQUENCED)
   {                  
      command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED;
      command.sendUnsequenced.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
   }                  
   else               
   if (packet -> flags & ENET_PACKET_FLAG_RELIABLE || channel -> outgoingUnreliableSequenceNumber >= 0xFFFF)
   {                  
      command.header.command = ENET_PROTOCOL_COMMAND_SEND_RELIABLE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
      command.sendReliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
   }                  
   else               
   {                  
      command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE;
      command.sendUnreliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
   }                  
   //将包放入待发送的队列中。包数据在packet.data,包长度为packet.dataLength
   if (enet_peer_queue_outgoing_command (peer, & command, packet, 0, packet -> dataLength) == NULL)
     return -1;       

   return 0;          
}                     

存放在待发送数据队列函数为下面的函数:

ENetOutgoingCommand *
enet_peer_queue_outgoing_command (ENetPeer * peer, const ENetProtocol * command, ENetPacket * packet, enet_uint32 offset, enet_uint16 length)
{
    //这个才是真正发送的结构体
    ENetOutgoingCommand * outgoingCommand = (ENetOutgoingCommand *) enet_malloc (sizeof (ENetOutgoingCommand));
    if (outgoingCommand == NULL)                                                                                                                                                        
      return NULL;

    outgoingCommand -> command = * command;
    outgoingCommand -> fragmentOffset = offset;
    outgoingCommand -> fragmentLength = length;
    outgoingCommand -> packet = packet;
    if (packet != NULL)
      ++ packet -> referenceCount;
    //发送函数,参数包括对端以及发送内容(实际上是将待发送数据加入list中)
    enet_peer_setup_outgoing_command (peer, outgoingCommand);

    return outgoingCommand;
}

enet_peer_setup_outgoing_command (peer, outgoingCommand)函数下面再讲

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值