转载

Jump The Great Firewall【step16 优化丢包率】

一、为何会丢包

经过博主长期使用的经验所得,使用UDP协议在互联网上传输数据时,存在一定的丢包率。尤其是在晚间繁忙时段,丢包率更为明显,那么我们如何进行优化来降低丢包率呢?

二、如何解决

  1. 服务器端与客户端同时进行校验,在一定时间内如果发现有丢包时,发送一条新的消息通知对方重新发送该条消息
  2. 服务器端与客户端在发送消息时,每次都将一条消息发送多次

我们先来看下第一种方案:这种方案属于最传统的方式,不过该方法有一个缺点。当网络状况非常差时,发出去的请求重发消息也可能会丢失,因此对端可能会再次请求丢失的那个请求重发的报文。与TCP类似,这将导致整个网络变的更差。

让我们来看下第二种方案:对于每一条消息,两端都进行了多次的发送,理论上整体带宽将被降低。在网络状况不好的情况下,假设一条消息我们发送5次,实际上并不会这么巧合的这5次都被丢包了。因此我更倾向于这个方案,在实际测试过程中我们发现带宽并没有降低,反而下载文件的速度比以前更稳定了。

三、如何实现

    1. 首先修改最底层的发包函数write_c
      ssize_t write_c(client_t* client, const void* buf, size_t count) {  unsigned char i;  unsigned char successed = 0;  for (i = 0; i < qtun->multi_send; ++i) {   if (qtun->use_udp) {    if (sendto(qtun->remotefd, buf, (int)count, 0, (struct sockaddr*)&client->addr, sizeof(client->addr)) >= 0)     ++successed;   } else {    const char* ptr = buf;    size_t left = count;    while (left) {     ssize_t written = write(client->fd, ptr, (unsigned int)left);     if (written == 0)      return 0;     else if (written == -1) {      if (errno == EAGAIN || errno == EWOULDBLOCK) continue;      return -1;     }     ptr  += written;     left -= written;    }    ++successed;   }  }  return count; } 
      这里我们根据配置文件中的multi_send参数来决定要发送多少次,在TCP模式中multi_send参数总是为1
    2. 我们定义一个msg_state_t结构来保存每一个收到的消息
      typedef struct {     unsigned int   ident;     unsigned short idx;     unsigned char  used; } msg_state_t;
    3. 在client_t结构中我们总是记录MSG_MAX_TTL条收到的消息id
      msg_state_t        recv_msgs[MSG_MAX_TTL];
    4. 在收到一条消息时,我们需要优先检查对应client_t结构中的recv_msg表内是否已记录了该消息的序号,如果该表中已包含了该消息的序号,则需要将该消息丢掉

四、增强安全性

为了增强安全性,在新版本中qtun默认禁止局域网内与其他主机通信,通过在配置文件中指定use_local_forward标志来开机局域网内的通信。具体的实现方法为:在server_process函数中检查数据包的源地址与目的地址是否都为当前局域网内的,如果都是当前局域网内的数据包,则直接进行丢包

if (!qtun->use_local_forward &&                 check_ip_by_mask(ipHdr->saddr, qtun->localip, qtun->netmask) &&                 check_ip_by_mask(ipHdr->daddr, qtun->localip, qtun->netmask)) {                 return;             }

五、完整代码

完整代码可到 step16 中查看

版本号:1.1.0

日期:2015-06-13

正文到此结束
Loading...