socket s;
char* buf=new char[100000];1.循环send(s,buf[nPosition],100,0),直至将buf中的所有数据即100000字节全部送出;
2.send(s,buf,100000,0)请问:1和2在网络传输效率上有无区别,区别在哪里?
char* buf=new char[100000];1.循环send(s,buf[nPosition],100,0),直至将buf中的所有数据即100000字节全部送出;
2.send(s,buf,100000,0)请问:1和2在网络传输效率上有无区别,区别在哪里?
可能第2种的效率高一些,系统自己处理分组的时候应该比自己处理快
而且第1种还有一个返回处理,可能会慢一些
未抓住实质,等待达人解答。
所以,一次放入少量数据,首先增加了函数调用的次数,
增加了系统缓冲区分配的额外计算负担,另外,会影响系统对包大小的有效计算。
一次放入大量数据,系统缓冲区空间可能不够用,所以send(s,buf,100000,0)
并不一定把100000个字节都放入系统缓冲区,这种调用本身就是病态的。
典型的IO方法是这样的:
socket s;
char* buf=new char[100000];
unsigned int totlelen =100000 ;
unsigned int sendlen;
do
{
sendlen = send(s,buf,totlelen ,0);
totlelen -=sendlen ;
}while (totlelen >0);
接收数据同发送数据类似。
do
{
sendlen = send(s,buf,totlelen ,0);
if(sendlen == SOCKETERR)
{
int err = WSAGetLastErr();
if()
{
}
}
totlelen -=sendlen ;
}while (totlelen >0);
我这样阐述或许要清晰一些:
socket s;
char* buf=new char[100000];1.循环send(s,buf[nPosition],100,0),直至将buf中的所有数据即100000字节全部送出;
2.send(s,buf,100000,0);
请问:1和2分别被操作系统用分几次(或几个包)在网络上传输完成,此两种方式在网络传输效率上有的区别哪里?注意,此处不用论及多次send()调用的cpu开销,特问网络传输效率?
前者保证可以用MTU的包发出去,而后者有些包可能达不到MTU。
试想有一个漏斗,一次放一大瓢水放进去漏的快,还是一次放一汤匙漏的快些?
send(s,buf,100000,0); >= 循环send(s,buf[nPosition],100,0)
前者保证可以用MTU的包发出去,而后者有些包可能达不到MTU。
试想有一个漏斗,一次放一大瓢水放进去漏的快,还是一次放一汤匙漏的快些?
若send()一段数据,而此段数据未达MTU,那么此段数据什么时候能被操作系统发送出去,望有人能深入谈下这个问题。
1.代码执行的时间. 多次调用自然比不上一次调用的性能好了,执行的代码量也多嘛.
2.网络发送的时间.从程序缓冲到内核缓冲这个过程,有一个复制的过程吧?当程序缓冲的size大于内核缓冲,那自然是需要分多次的复制才能完成的,不过这样的话可以得到最少的复制次数.如果是非阻塞式的话.估计很麻烦,因为会发送失败.
这是针对tcp的.如果是udp,如果太大.嘿嘿.有可能发送失败,另外,udp最大的缓冲区也是有限制的(linux最大是64KB ?).不像tcp会自动分片发送.
我猜的,没有试过大数据量的发送.达人来说说看.
--
tcp是以窗口大小发送的吧.由网络状态决定,应该不是由MTU决定的吧
比如100000的字节都按照MTU=1000发送需要发送100次,如果按照小于1000的值发送就要大于100次。谁快谁慢不言而喻。
反正你必须判断send的返回值,太大了,还是得分多次发送。没用的。
已经说得很清楚了
看得出他很了解网络的底层
建议你使用第二种方法
send(s,buf,100000,0);
由系统自动去发会比你自己控制好
正如softrain所说MTU是系统动态试出来的
你很难知道用户现在网络的MTU呵
TCP的流控做得挺好的
是不能一次性发那么大的
会失败
而且用UDP的话
需要处理丢包的情况
根据传输的大小有不同的方法来处理
不过要自己去处理丢包的情况
实在是麻烦,
处理方法不对,效率更低
"没有达到MTU的,如果你设置了TIME_NODELAY就立即发送,如果没设置TCP就自动等到达到了MTU再发送“。如果既未设置TIME_NODELAY,又没达到MTU,这段数据岂不是不能被传输?
说到TCP对发送数据的控制涉及到TCP段、IP包的组织方式和TCP的诸多流控制算法(如拥塞控制算法)等的实现。你可以让所有的包都分成不超过MTU的512字节但你还是不能保证在传输到客户端过程中不会被再次分割,只要存在分割,就会出现包的丢失风险,效率肯定就比你先前预定的512字节或者10字节更保险的数据大小传输效率要低,但你又考虑到网络带宽的利用率对于你每次512字节或者10字节的传输效率相比是否也是效率不高呢?这是永远矛盾的东西,关键是看你要怎样的平衡。其实这是个对编程透明的问题,是属于操作系统自行决定处理的。所以说,楼主的对这个问题的讨论是空泛而注定不会有任何结果的。
一次发送的发送包量=数据量/MTU
循环发送的发送包量=数据量/自定义每个包的大小当自定义每个包的大小>MTU,tcp会将其分割,结果发送次数还是比一次的要多,发送次数越多,就越慢,特别实在广域网上很明显。关于NODELAY,就是Nagle算法
就是缓冲中的数据不是立即发送,而是等待一定的量或规定的时间到了就会发送。关闭后(设置NODELAY)效率会降低。楼主所问的“如果既未设置TIME_NODELAY,又没达到MTU,这段数据岂不是不能被传输?”
因为他还有时间间隔,好像是200ms,间隔到了就发送。具体算法你要看看书上说的,这里很多说法我认为并不准确,包括我自己的见解。
关于其他详细的,请看一下《TCP/IP详解第一卷》,很多具体内容我记不得了,你还是自己看一下书吧。
一定看一下 TCP/IP详解
关于路径MTU发现你可以参考RFC1981文档,该文档描述了对于IPv6的路径MTU探索。它很大程度上是从RFC1191(描述了对于IPv4的路径MTU探索)发展而来的。而在其
“5.4 TCP层动作
TCP层必须通过一种连接记录路径上的PMTU;它不能发送可能导致分组大于PMTU的分段。一个简单的执行过程应当在每次建立新的分段时询问IP层相应的值,但是它的效率很低。”
里已经很明确指出了TCP是必须“询问IP层相应的值”。就是说,IP层里才有保存分割信息的起码数据结构,你先看看IP头的结构与TCP头的结构就会明白。在TCP头里根本没有Fragment Offset(13-Bits)和分割Flags(3-Bit)。你回帖里写的“×TCP头部的32位序列号标识了报文段中的第一个字节的“偏移””的TCP头部的32位序列号其实只是标志数据流的32-Bit Sequence Number。与IP头里的Fragment Offset(13-Bits)分块偏移根本是两个概念,不要被弄混淆了。
TCP的32位序列号就是用来标识顺序的,比如上面的760的标号=1,264标号=2,他们到达目的地就会按照标号来重新组织起来。
这样说,阁下清楚了没有?还有,阁下的理解我是越来越不懂了,如果阁下愿意,可以将你的理解详细说一下。
所以microsoft建议在适当的地方使用TransmitFile。
Nagle算法不仅仅是根据MTU来决定是否发送数据的。比如间隔500ms以上,你即使发送1bit,网络层也会立刻把这1bit的数据发送出去。接着你第二次发送1bit数据,Nagle算法就启用MTU控制了。