收录日期:2020/11/29 20:44:21 时间:2016/06/03 11:07:29 标签:网络编程
两台公众网上的机器用PCAnywhere连接起来后,用PCAnywhere传输文件,速度能达到约50K Byte/s的速度传输文件,一个700K的文件,也就是几秒钟能够传输完成。

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

请问,可能原因是什么,如何解决?
谢谢!
PCAnywhere很可能采用了多线程,将大文件分成N份用N个线程同时发送。
我在做HTTP下载时,只要服务器没限制连接数,用10个线程同时下比flashGet快多了。
一般不推荐用MFC::CSocket的吧
我宁愿自己写一个
自己写程序实现通信,传输700k的文件,起码需要半个多小时。
你的程序一定有问题!在局域网上先试一下!排除网络的问题!
谢谢大家关心!

事实上,我也正在希望我的程序有问题,主要是我实在不知道问题在那里。

测试程序很简单,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;
               }
          }
     }
}
我听说,传输大的文件要用winsock套接字比较好,用MFC套接字如CSocket或CAsyncSocket可能会传输错误或数据不正确。这是我听说的。仅供参考!!!!~
哈哈~网的信息也许太多
我当时也是找了很久才找到
网上传送时,要控制的不[发送端]而是[接收端]
//接受端
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


在可编辑的iframe里删除图片,怎样得到我删除图片原来的连接地址?! 高分请教,关于图标转换问题,只要解决,保证送分,急急急!! 高手快來,這個SQL怎麽寫,在線給分!!! 哪里有《Windows95 系统编程奥秘》HTML版(中文)?? 急救,请大家帮忙! 那位帮忙看看,挺简单的,可我就是没想通。 高分请教,关于图标转换问题,只要解决,保证送分,急急急!! faint,难道VC对textout的个数还有限制??? 请问:system.threading中的thread以及thread的start,sleep是如何工作的? 庆祝围巾出狱 chinajiji(菜鸟叽叽) 进来!还有认识他和认识我的也进来! Oracle 的 Logfile問題 请问:system.threading中的thread以及thread的start,sleep是如何工作的? 安装VC++时的巨大问题!(2000的系统NTFS) 高分请教,关于图标转换问题,只要解决,保证送分,急急急!! 高分请教,关于图标转换问题,只要解决,保证送分,急急急!! 怎样在程序中实现拖动圆形图像,要求实现图像拖动的实时效果,也就是运动轨迹 安装VC++时的巨大问题!(2000的系统NTFS) 支持解封围巾兼批斗“你发了40个同样的帖子被删,那要找到40个不同的ID支持解封你的帐号就解封。” 某要分无用! 我写了一个类是从TCustomControl派生,我想给他加上 caption属性让他在设计时上面就有caotion,就象按忸控件一样拉上来就有一个\"button1\"? 请问如何将MEMO的背景设置为图片?? 这里的问题最最刁!!!!!! 在c#中如何连接Paradox数据库? 请问怎么用ASP.NET做一个Web Mail的收发系统? 怎样从LONG型字段中取出字符串 在做c/s数据库程序时,用vf+sql和delphi+sql哪一个种更好些? QQ密码忘了怎么办? 在UDP定义中,sin.sin_port = htons(0); 的0是何意思?是否只要在sendto指定对方地址就可以,本方port不用指定,除非也要收。 高分请教:上传图片到特定的目录,在线等待!~~~~~~~~