一、为何会丢包
经过博主长期使用的经验所得,使用UDP协议在互联网上传输数据时,存在一定的丢包率。尤其是在晚间繁忙时段,丢包率更为明显,那么我们如何进行优化来降低丢包率呢?
二、如何解决
我们先来看下第一种方案:这种方案属于最传统的方式,不过该方法有一个缺点。当网络状况非常差时,发出去的请求重发消息也可能会丢失,因此对端可能会再次请求丢失的那个请求重发的报文。与TCP类似,这将导致整个网络变的更差。
让我们来看下第二种方案:对于每一条消息,两端都进行了多次的发送,理论上整体带宽将被降低。在网络状况不好的情况下,假设一条消息我们发送5次,实际上并不会这么巧合的这5次都被丢包了。因此我更倾向于这个方案,在实际测试过程中我们发现带宽并没有降低,反而下载文件的速度比以前更稳定了。
三、如何实现
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
typedef struct { unsigned int ident; unsigned short idx; unsigned char used; } msg_state_t;
msg_state_t recv_msgs[MSG_MAX_TTL];
四、增强安全性
为了增强安全性,在新版本中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