微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

无法通过无线网络上的UDP广播快速发送

如何解决无法通过无线网络上的UDP广播快速发送

我编写了以下代码,用于通过无线网络上的广播传输UDP数据包。我尝试开发的应用程序需要非常快速地传输数据包,但是不幸的是我无法这样做,因此需要增加睡眠时间。我发现在500us的睡眠时间以下,我无法成功发送所有数据包。 为什么睡眠时间必须这么长? 是否可以通过进一步优化此代码来减少此时间? 如果我不处理接收到的数据包缓冲区,可以吗?还是会产生问题? 请注意,我正在使用OpenWrt运行的无线电中运行此代码。 提前致谢。 码:
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <netdb.h>
#include <stdio.h>

#include <fcntl.h>
#include <string.h>
#include <sys/time.h>
#include <arpa/inet.h>  /* for sockaddr_in */

#define broADCAST_IP \"192.168.255.255\"
#define broADCAST_PORT 45454

int b_sock=-1;

void init_socket()
{
  unsigned short b_port = broADCAST_PORT;
  struct sockaddr_in b_addr;
  int broadcastPermission;
  char* rx_ip = broADCAST_IP;

  if ((b_sock = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP)) < 0)
    perror(\"socket() Failed\");

  /* Set socket to allow broadcast */
  broadcastPermission = 1;
  if (setsockopt(b_sock,SOL_SOCKET,SO_broADCAST,(void *) &broadcastPermission,sizeof(broadcastPermission)) < 0)
    perror(\"setsockopt() Failed\");

  int opts;
  opts = fcntl(b_sock,F_GETFL);
  if(opts < 0)
    perror(\"fcntl get Failed\");

  opts = (opts | O_NONBLOCK);
  if(fcntl(b_sock,F_SETFL,opts) < 0)
    perror(\"fcntl set Failed\");

  memset(&b_addr,sizeof(b_addr));   /* Zero out structure */
  b_addr.sin_family = AF_INET;                 /* Internet address family */
  b_addr.sin_addr.s_addr = inet_addr(rx_ip);/* broadcast IP address */
  b_addr.sin_port = htons(b_port);         /* broadcast port */

  if (bind(b_sock,(struct sockaddr *) &b_addr,sizeof(b_addr)) < 0)
    perror(\"rx bind() Failed\");
}

void send_thread_body(long int buf,struct sockaddr_in tx_addr)
{
  if(sendto(b_sock,&buf,sizeof(long int),(struct sockaddr *)&tx_addr,sizeof(tx_addr)) < 0)
    printf(\"tx sent diff num bytes than expected: %d\\n\",buf);
}


int main(int argc,char *argv[])
{
  init_socket();
  {
    timeval start,end;
    double diff = 0;
    long int num = 0;

    char *tx_ip = broADCAST_IP;
    unsigned short tx_port = broADCAST_PORT;
    struct sockaddr_in tx_addr;

    memset(&tx_addr,sizeof(tx_addr));   /* Zero out structure */
    tx_addr.sin_family = AF_INET;                 /* Internet address family */
    tx_addr.sin_addr.s_addr = inet_addr(tx_ip);/* broadcast IP address */
    tx_addr.sin_port = htons(tx_port);         /* broadcast port */

    double next = 0;
    double st = 0;

    while (num<50000)
    {
      while (st <= next)
      {
        gettimeofday(&start,NULL);
        st = start.tv_sec*1000 + ((double)start.tv_usec)/1000.0;
      }

      send_thread_body(num,tx_addr);

      gettimeofday(&end,NULL);
      diff += ((double)(((end.tv_sec - start.tv_sec)*1000000 + (end.tv_usec - start.tv_usec))))/1000000.0;

      num++;

      next = end.tv_sec*1000 + ((double)end.tv_usec)/1000.0 + 0.7;
    }

    printf(\"Avg time diff: %f\\n\",diff/50000.0);
  }
  close(b_sock);
  return 0;
}
    

解决方法

        您可能将套接字缓冲区溢出,因为您将套接字设置为“ 1”。通常(启用阻塞时),如果套接字缓冲区已满,则“ 2”会阻塞,直到有足够的缓冲区空间来保存要发送的消息。 从http://pubs.opengroup.org/onlinepubs/009695399/functions/sendto.html:   如果没有足够的空间   发送套接字以将消息保存到   被传输和套接字文件   描述符没有O_NONBLOCK   设置,sendto()应该阻塞直到空间   可用。如果没有空间   可在发送插座上找到   保留要发送的消息,并   套接字文件描述符确实有   O_NONBLOCK置位,sendto()将失败。 在
sendto
调用之间添加
sleep
时,可以有效地限制吞吐量并防止套接字缓冲区溢出。 您应该使用屏蔽插座,而不是ѭ3。如果套接字缓冲区已满,则“ 2”将阻塞,这与休眠实际上是相同的,不同之处在于套接字将能够保存您的下一个数据报时,它将自动停止休眠。 为了获得更好的吞吐量,请尝试将数据集中到接近MTU大小的数据报中(同时注意为UDP / IP标头保留足够的空间)。与发送非常短的数据报相比,这应该给您较小的报头开销。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。