最近由于工作需要,开发一个网络库,从中发现了一些不可思议的问题!不做不知道一做吓一跳。先介绍一下我库的使用环境。主要在局网内传输大数据!由于上头的人对UDP的执迷,所以第一个版本为UDP版,但最终与要达到的目标相差甚远。广播的传输速度只有1M左右,点对点的传输速度在3M~4M。与每秒9M左右的目标相去甚远。所以最终放弃用UDP来实现大数据的可靠传输,改用TCP来实现。(前期所做的一切就是用UDP来实现一个类似TCP的协议)UDP进行可靠数据传输开发,在UDP每次发送数据前底层的协议是先连接一下远端主机,然后在发送数据,发送完毕在释放所建立的临时连接。因此为了不每次创建临时连接可以先连一次然后用send发送,接收端也可先连然后recv。这种情况下一般会提高UDP传输性能30%以上。并且由于连接的建立,UDP还可收到数据能否到达对应主机的通知,因此在进行UDP传输时最好先连接。TCP版也很快实现了,但对监听端口我使用了非堵塞SOCKET,(WSAWaitForMultipleEvents)在一个监听线程中我等待FD_ACCEPT事件的发生。然后调用accept。在此发现一个奇怪的现象,当客户端请求连接很密结时,有可能收不到FD_ACCEPT事件,我分析可能是由于前一个连接请求还未处理完毕下一个又到达,最终造成FD_ACCEPT事件混乱,可能只有一种状态。如果在两次请求之间间隔一段时间,就能很好的运行。但你不能这样去要求客户。因此我改用堵塞方式。(我想Microsoft事件对象的内部实现可能只有两种状态,TRUE或FASE,因此当多个请求同时到达时就不能很好的记数,以至于造成状态混乱。纯属猜测!)现在在局网内的流速能达到10M左右,基本合乎要求。这是我的一点开发经历,希望对大家有所帮助。如果有不对的地方请指出!(异步方式有很多但我只有了WSAWaitForMultipleEvents ‘事件’)

解决方案 »

  1.   

    我有几个地方不太明白, 希望能与你探讨
    1. udp是面向无连接的协议, 不知道您说的【在UDP每次发送数据前底层的协议是先连接一下远端主机】,这句话的真正含义
    2. 你说的【FD_ACCEPT事件混乱】,我认为不是这样的, listen过程中, 能够处理的并发连接数是有一定限制的, 也就是同一时间只能处理的连接数不是无限的,这时候应该提示用户服务器繁忙,我的理解是这样的。
      

  2.   

    在UDP每次发送数据前底层的协议是先连接一下远端主机, 怎样连接啊??不明白!!
      

  3.   

    对啊,udp建立连接怎么回事?
      

  4.   

    不用连接的,CREATE后就可以直接SENDTO/REVFROM,当然也可以BIND也可以不BIND,依赖具体需要
      

  5.   

    UDP同样可连接的,但它不象TCP那样需要三次握手。在底层,连接的UDP套接字,其实质就是与远端主机端口与地址相绑定。在向同一目标发送大数据时可以使用这种方法,这也是最优方式。在不同的系统下,UDP的实现不一样,但一般情况都能获得30%的性能提升。
      

  6.   

    striking(硬撑者) ( ) 信誉:109 :“你说的【FD_ACCEPT事件混乱】,我认为不是这样的, listen过程中, 能够处理的并发连接数是有一定限制的, 也就是同一时间只能处理的连接数不是无限的,这时候应该提示用户服务器繁忙,我的理解是这样的”不是你所说的! 我的连接等待数不会超过等待队列的最大值,我所说的是它在很短的时间内同时接收多个连接(2或3个)事件;就会产生我所说的现象。你所说的是等待队列的大小,也就是listen(5)后的那个参数,我在每一时的连接等待队列不会超过它。因为我在随时处理到达的连接。
      

  7.   

    不用连接的,CREATE后就可以直接SENDTO/REVFROM,当然也可以BIND也可以不BIND,依赖具体需要
    --------------------------------------------
    给说这话的仁兄一个提示。
    也请各位注意:
     udp的socket也可以是面向联机的,我们暂时就叫它虚拟连接吧
    ::connect(sock,...serverip,serverport);
    ::send(sock,data,datalengyth,null);
    sock是一个udp的sock,这么用没有问题。
    但是这种用法好多资料上都没有提供,
    但是,其实正如楼主讲的一样,这种用法在发送大数据时,确实效率挺高
      

  8.   

    我觉得楼主所说的UDP连接是有道理的,UDP本来是面向无连接的不可靠的传输,可是也可以经过编程处理变成可靠的面向连接的传输.
    这有点像IP层是无连接且是非可靠的,而用上一层TCP实现可靠的面向连接的道理一样
      

  9.   

    TCP版也很快实现了,但对监听端口我使用了非堵塞SOCKET,(WSAWaitForMultipleEvents)在一个监听线程中我等待FD_ACCEPT事件的发生。然后调用accept。在此发现一个奇怪的现象,当客户端请求连接很密结时,有可能收不到FD_ACCEPT事件,我分析可能是由于前一个连接请求还未处理完毕下一个又到达,最终造成FD_ACCEPT事件混乱,可能只有一种状态。如果在两次请求之间间隔一段时间,就能很好的运行。但你不能这样去要求客户。因此我改用堵塞方式。
    ======================================
    WINDOWS的事件队列大小有限,若不能够及时取走,是会被WINDOWS丢弃的,消息的情况也差不多accept的响应务必要快速,否则出现堵塞降被丢弃。
    我一般是使用缓存队列+线程处理的方式来完成这种工作,
    accept仅仅简单的进入缓存队列,队列中的连接状态处理工作则由线程来处理
      

  10.   

    关于UDP连接的事情就不用多说了,至少有人声援了我。证明我是正确的,事实也是如此。关于事件混乱的事情可能正如 flowlight(流光) 所说,看来还是我的失误。我的过程已够短够快了,看来那里最好什么也不做,接收后就压入队列。
      

  11.   

    to SAM2002:
    你好,我现在在pda上用iax协议做一个语音通话的小程序,实现tcp和udp两种方式,我发现用tcp通话时,系统反应还挺迅速;用udp时虽然通话质量高,但想在通话同时做点别的操作_比如说浏览网页,系统反应很慢;我想跟您说的udp connect有一定关系.
    我想问下,当我在通话开始时如果跟对端connect(udp)一下的话,后面发送函数是用send还是sendto呢?另外是不是要为语音通道专门开一个端口以避免通话过程中控制帧的干扰呢??
      

  12.   

    10MBps还是10Mbps,这可是相差8倍的.
      

  13.   

    udp的send也许少了sendto里的对dest Addr的处理,缩短了运转周期,而所谓的事件混乱,你试试两次setevent,后再试能wait几个event。
      

  14.   

    to :NTSystem() ( ) 信誉:100 
    是10M字节/秒。to :danyuhao(诸葛不如) ( ) 信誉:100 
    连接后就用 send与recv;未连接就用sendto 与 recvfrom。
      

  15.   

    to :danyuhao(诸葛不如) ( ) 信誉:100 控制帧如果很频繁的话应该有影响,如你所说可以开一个端口与线程来单独处理。视情况而定吧!
      

  16.   

    to:SAM2002
    请问如果使用UDP连接方式是否可以解决广播视频不流畅的问题。
    另外还有什么方法可以提高广播视频的流畅程度(除了降低颜色数)
      

  17.   

    to:roc_zhang(好好学习)连接后的UDP可以提高传输速率;但对你的视流畅的贡献有多大我也不太清楚。
      

  18.   

    UDP面向连接只是把一段数据的传输目标固定在某个IP上,并没有建立确切的连接,数据传输速度的提高也不过是不用每次数据发送重新定位