新浪博客

UDP Socket 广播中sendto()耗时过长

2012-10-18 10:51阅读:
UDP Socket 广播中,sendto()将数据发送到一个结尾为“255”的IP地址,应用中发现sendto()函数耗时过长。参考了“http://topic.csdn.net/t/20040722/22/3201560.html”中的内容后,经过在自己的局域网内实验,得到以下经验:
1、广播到“*.*.*.255”耗时很长(此时局域网内只要很少机台机子工作并接受该广播数据,而不是整个IP段的机子都在工作),可以用setsockopt函数设置sendto的超时时间:
SetSendTimeOutValue(unsigned int usec)
{
    if( !IsValid() ) return false;
    int sta = -1;
    int msec;
    msec = usec/1000;
    if(msec < 1) msec = 1;
    unsigned int seco  = (unsigned int)usec/1000000;
    unsigned int useco = usec00000;

    struct timeval tv_out;

    tv_out.tv_sec  = seco;
    tv_out.tv_usec = useco;
#ifdef _WIN32
    sta = setsockopt(isocket, SOL_SOCKET, SO_SNDTIMEO, (char *)&msec, sizeof(msec));
#else
    sta = setsockopt(isocket, SOL_SOCKET, SO_SNDTIMEO, &tv_out, sizeof(tv_out));
#endif
    if(sta == 0 ) return true;
    return false;
}

此时,耗时会按照函数中的设置变短,但是丢数据的情况会增加(即:实际在线的计算机不能接收到所有的广播数据包,丢包率比sendto()耗时长的情况下增加了很多)。
2、如果不用UDP广播,而是点对点UDP Socket传输(即,只把数据发送到某一台在线的计算机IP),速度很快,sendto()耗时几乎为0.但是这又无法满足一点发数据多点接受数据的目的。再研究一下UDP 多播,看看能否解决该问题。
3、UDP 多播耗时比广播耗时短,但是还是在1000us左右,不能满足要求。点对点UDP传输耗时很短,但是“端口复用”不能用,只有最后启动的一个终端能够读取到数据。继续调研中。
4、最后只能用折衷的解决方法。用UDP单播,向每台需要数据的计算机sendto()两次数据(两个不同的端口),还好每台机子只会启动两个server来接受数据,所以只需要2个端口就可以了。这中情况下,虽然向每台机子send两次数据,但是只要计算机在线,耗时也非常短。
freebsd与linux下bind系统调用小结(转自http://blog.csdn.net/lwhsyit/article/details/3279439
只考虑AF_INET的情况(同一端口指ip地址与端口号都相同)
1.freebsd支持SO_REUSEPORT和SO_REUSEADDR选项,而linux只支持SO_REUSEADDR选项。
2.freebsd下,使用SO_REUSEPORT选项,两个tcp的socket可以绑定同一个端口;同样,使用SO_REUSEPORT选项,两个udp的socket可以绑定同一个端口。
3.linux下,两个tcp的socket不能绑定同一个端口;而如果使用SO_REUSEADDR选项,两个udp的socket可以绑定同一个端口。
4.freebsd下,两个tcp的socket绑定同一端口,只有第一个socket获得数据。
5.freebsd下,两个udp的socket绑定同一端口,如果数据包的目的地址是单播地址,则只有第一个socket获得数据,而如果数据包的目的地址是多播地址,则两个socket同时获得相同的数据。
6.linux下,两个udp的socket绑定同一端口,如果数据包的目的地址是单播地址,则只有最后一个socket获得数据,而如果数据包的目的地址是多播地址,则两个socket同时获得相同的数据。

我的更多文章

下载客户端阅读体验更佳

APP专享