两台公众网上的机器用PCAnywhere连接起来后,用PCAnywhere传输文件,速度能达到约50K Byte/s的速度传输文件,一个700K的文件,也就是几秒钟能够传输完成。自己用MFC写程序连接,采用tcp/ip协议建立连接,使用了CAsyncSocket建立连接, SOCK_STREAM类型。发送方,不停地发送数据,或者在CAsyncSocket::OnSend中发送数据,接受方在OnReceive中接受数据,速度爆满,顶多有几百字节/秒的传输速度。
如果发送方的报文,也就是每一次CAsyncSocket::Send的报文大小,设置为1K以上,那么,很可能就堵塞了:很长时间过不来,然后突然间可能过来了。
如果发送方的报文,也就是每一次CAsyncSocket::Send的报文大小,设置为256或者更小,则报文能断断续续过来,可是仍然爆慢。
另外发送方的发送缓冲区,如果设置为很大,则大多数报文反而被堵塞。
自己写程序实现通信,传输700k的文件,起码需要半个多小时。相比PcAnywhere的传输速度,一个天上一个地下,可是,不知道为什么?请问,可能原因是什么,如何解决?
谢谢!

解决方案 »

  1.   

    PCAnywhere很可能采用了多线程,将大文件分成N份用N个线程同时发送。
    我在做HTTP下载时,只要服务器没限制连接数,用10个线程同时下比flashGet快多了。
      

  2.   

    一般不推荐用MFC::CSocket的吧
    我宁愿自己写一个
      

  3.   

    谢谢大家关心!事实上,我也正在希望我的程序有问题,主要是我实在不知道问题在那里。测试程序很简单,server端,一个CAsyncSocket的派生类对象,实现侦听功能,侦听成功后,Accept一个CDataSocket对象。Client端,一个CDataSocket对象,直接Connect Server端的Listen地址和端口。然后不对CDataSocket对象做处理,Server端开始向其发送数据。不停地发,直到发不出去(或者文件结束),如果发不出去,则等待。Client端,则在OnReceive中Receive数据。仅此而已。
    现在可以说说今天努力的结果了:1,如果不对socket做任何处理,如果Server端发送的数据报文每次大小(也就是CAsyncSocket::Send的大小)为256字节以下,则已开始能传输,后来就很容易堵塞,然后堵塞很长时间,突然间,能过来一段数据;这个显然不是我想要的结果。如果Server端发送的数据报文每次都比较大,比如>1024,则很容易堵塞。2,后来对Socket作了处理,第一个处理是限制发送缓冲区的大小,这样,我只要发送几个数据报文,发送缓冲区就满了,后面的数据只有等待了。我用了CAsyncSocket::SetSockOpt——好像是这个函数——把发送缓冲区限制为256/512字节,效果已经渐渐明显起来,已经基本上不堵塞了,不过,传输速度依然很慢;只是基本上不堵塞了。报文大小设定为128字节,效果最好;3,为了再次提高速度,又设定了两个参数,如下(都是CAsyncSocket::SetSockOpt实现的):
    (1)TCP_NODELAY=TRUE
    (2)SO_DONTROUTE
    这么设定之后,速度大大提高,传输700K,最快的速度,我调试出来是2分钟左右。可是距离PcAnywhere传输的速度依然慢很多(它这个基本上30-40秒能搞定)不过,对我现在来说,已经是一个很大的进步了!每个报文设定为128字节,则总传输时间约在2分钟左右,如果设定为68字节,则总传输时间约在4分半左右。en.现象就是这样,代码很简单,可惜,在公司,否则我就copy上来了。
    凭我的记忆,写上一点关键代码://接受端
    void CDataSocket::OnReceive(int nErrorCode)
    {
        if (nErrorCode == 0)
        {
           char buf[1024];
           while (true)     // loop until break
           {
                int n = Receive(buf, 1024);
                if ((n == 0) || (n == -1))
                {
                      break;
                }
           }
        }
    }//发送端
    #define PACKET_SIZE  128
    void CDataSocket::SendData(int len, char* buf)
    {
         int n = 0;
         while (n < len)
         {
              int m = CAsyncSocket::Send(buf + n, min(PACKET_SIZE, len - n));
              if (m > 0)   n += m;
              else if (m == -1)
              {
                   if (CAsyncSocket::GetLastError() != WSAEWOULDBLOCK)
                   {        // error
                         break;
                   }
              }
         }
    }
      

  4.   

    我听说,传输大的文件要用winsock套接字比较好,用MFC套接字如CSocket或CAsyncSocket可能会传输错误或数据不正确。这是我听说的。仅供参考!!!!~
      

  5.   

    哈哈~网的信息也许太多
    我当时也是找了很久才找到
    网上传送时,要控制的不[发送端]而是[接收端]
    //接受端
    void CDataSocket::OnReceive(int nErrorCode)
    {
        if (nErrorCode == 0)
        {
           char buf[1024];
           int nTotal = TOTAL  //实际文件大小
           while (nTotal)     // loop until break
           {
                int n = Receive(buf, nTotal);
                if ((n == 0) || (n == -1))
                {
                      break;
                }
                nTotal -= n;
           }
        }
    }//发送端
    如果有足够的空间,一次发100M也可以
    如果没有,也可以分段读入文件
    void CDataSocket::SendData(int len, char* buf)
    {
         int n = 0;
         int m = CAsyncSocket::Send(buf , len);
         if (m == -1)
              {
                   if (CAsyncSocket::GetLastError() != WSAEWOULDBLOCK)
                   {        // error
                         break;
                   }
              }
    }流程
    发送端:
    1)发送一个结构(含文件大小)
    2)发送文件
    接收端
    1)接收自义结构
    2)根据文件大小,接收文件
    我的例程
    http://www.vckbase.com/code/listcode.asp?mclsid=9&sclsid=919