关于UDP的sendto函数发送成功与否对发送速度的影响,请高手来看看

horace331 2004-07-22 10:51:06
我用一个FOR循环(20个)发送一个数据块到一组IP地址上,如果所有的IP地址都是真实的并且有活动的机器,只需要0毫秒就可以发完.
但是如果在指定IP地址上没有机器,sendto()好像要反复重试一样,没有要花50-6000毫秒不等,大大增加了程序的周期.

我觉得应该是socket字上设定的问题,但不知道问题在哪里,请高手指点一下
...全文
2503 46 打赏 收藏 转发到动态 举报
写回复
用AI写文章
46 条回复
切换为时间正序
请发表友善的回复…
发表回复
tukey 2005-02-27
  • 打赏
  • 举报
回复
mark
horace331 2004-08-04
  • 打赏
  • 举报
回复
sckTimedout 10060 已关闭套接字。
证明是sendto响应一个超时的控制,确实是我在setsockopt设定的1000ms。
然后我把控制时间加大,发现数据都可以发送成功,只是都花了2002-2004ms,看来sendto内部有一个自己的超时控制,只是我以前时间设定比较短,所以才得出错误结论。
horace331 2004-08-04
  • 打赏
  • 举报
回复
我的缓冲区是65536K,单次发送是8196K,但是发送第一个1025K的时候就报错,所以不是缓冲区满的问题,再说如果满了系统也会自己处理而不会报错,因为如果输入的是正确地址可以非常快速的发送,1S可以发好几百次,你可以把IP换成自己的机器是一下。

可能是套接字无效之类的错误,我检测了一下,报的错是10060 已关闭套接字,不过我不太明白原因。
toxyboy 2004-08-03
  • 打赏
  • 举报
回复
Mark
horace331 2004-08-03
  • 打赏
  • 举报
回复
to fengge8ylf:
那sendto函数返回的值有是什么呢?难道只是返回是否成功把数据拷到系统缓冲区?如果这样的话就不可能有失败呀.因为作为UDP协议又不需要握手协议,系统内部拷贝后就不用管了,为什么还会返回发送失败?而且在数据块的大小可以直接影响发送结果,至少证明sendto有一定的检测发送是否成功的能力.

我比较同意footway(靠边行走) 的观点,"RFC规定IP在任何时候都不等ARP解析完成就发送了,这样的发送会使IP报文丢弃,发送失败。但如果IP需要分片,则保证最后一片的发送,也就是最后一片是等到ARP解析完成后才发送的",所以当数据包大于1K,sendto就要参考ARP解析的结果,如果解析结果为空,则认为发送失败,放弃拷贝,返回ERR.
fengge8ylf 2004-08-03
  • 打赏
  • 举报
回复
大家注意sendto只是把应用层的数据拷贝到系统缓冲区中(IP缓冲区?),实际上就是数据拷贝,而不是真正的发送。而发送则由TCP/IP来处理的,对于UDP来说应用层根本不知道数据有没有发送成功
horace331 2004-08-03
  • 打赏
  • 举报
回复
前段时间忙别的去了,没有回来讨论问题,现在继续.
上次我贴的程序只是模仿我正在做的项目,所以不带针对性,现在我把循环改了改,大家再试试,然后都说说自己的想法.
// TestSendTo.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <stdio.h>
#include <winsock2.h>
int main(int argc, char* argv[])
{
DWORD LastTime;
DWORD Curtime;
DWORD EscpTime;
WSADATA wsaData;
long addr;
long wrc;
long lngSendTimeOut = 1000;
long lngRecvTimeOut = 1000;
SOCKADDR_IN sockObject;
SOCKET sSend;
char transbuf[1025] ; //这是BUF的大小,也是直接影响发送结果的地方
char IPADDR[17];
memset(transbuf,'a',sizeof(transbuf));

WSAStartup(0x202,&wsaData);
sSend = socket(AF_INET, SOCK_DGRAM,0);
setsockopt(sSend,SOL_SOCKET,SO_SNDTIMEO, (char*)&lngSendTimeOut,sizeof(lngSendTimeOut) );
setsockopt(sSend,SOL_SOCKET,SO_RCVTIMEO,(char*)&lngRecvTimeOut,sizeof(lngRecvTimeOut) );
sockObject.sin_port = htons(3500);
sockObject.sin_family = AF_INET;
for(int i = 1;i < 60000; i++)
{
sprintf(IPADDR,"192.168.1.254"); //这是IP地址,随便改写都可以
LastTime = GetTickCount();
addr = inet_addr((char *)IPADDR);
memcpy(&sockObject.sin_addr,&addr,sizeof(addr));

wrc = sendto(sSend,transbuf,sizeof(transbuf),0,(struct sockaddr *)&sockObject,sizeof(sockObject));
Curtime = GetTickCount();
EscpTime = Curtime - LastTime;
if (wrc != SOCKET_ERROR)
{
printf("Send %ld Data To %s,Use Time:%d ms\n",i,IPADDR,EscpTime);
}
else
{
printf("Send %ld Data Failed!\n",i);
}
}
WSACleanup();
return 0;
}
fengge8ylf 2004-08-03
  • 打赏
  • 举报
回复
horace331() 当然会返回失败啊 比如缓冲区满了 套接字无效之类的错误
sharkhuang 2004-07-31
  • 打赏
  • 举报
回复
如果小于1K即一个包,不管ARP是否解析出MAC地址都会直接发送

不会吧
sharkhuang 2004-07-31
  • 打赏
  • 举报
回复
以太网传输MTU是1500.所以减去以太贞头的大小(具体多少不记得了)n.
所以大雨1500-n的包才会被分片啊!
Sander 2004-07-31
  • 打赏
  • 举报
回复
我想原因是这样的:
你send的data size < driver fifo buf size,实际是放到 driver buf .
so timeout is 0.

if send data size>driver fifo buf size and no Dest IP then display "Failed!"
还有原因是你new 的socket是 block的(default)
Sander 2004-07-31
  • 打赏
  • 举报
回复
请改code:
sprintf(IPADDR,"192.168.1.1%02d",i);
Sander 2004-07-31
  • 打赏
  • 举报
回复
我的结果:
Send Some Data To 192.168.1.1 1,Use Time:47 ms
Send Some Data To 192.168.1.1 2,Use Time:0 ms
。。。。。。
Send Some Data To 192.168.1.134,Use Time:0 ms
lostgdi731 2004-07-30
  • 打赏
  • 举报
回复
to horace331():
sendto函数就是使数据发送到传输层.那你有必要管它接着怎么发送吗?你得到sendto函数返回的时间只是它完成发送到传输层的时间,接下来不是sendto处理的.(网络分层的原理)
footway 2004-07-29
  • 打赏
  • 举报
回复
我想这个与配置无关,但我就觉得奇怪了,如果“但如果IP需要分片,则保证最后一片的发送,也就是最后一片是等到ARP解析完成后才发送的”,那你并不能解析那些机器的MAC,为什么也可以发出去呢?

===============
我也奇怪了。我这里只有一台电脑,通过HUB和ADSL猫相连,运行的结果如上面。

估计sendto只是把UDP数据报提交到IP层就返回了,而IP层只把数据报提交到链路层就返回了,链路层能不能发送成功上面的层可能是不知道的。

MS要是能公开TCP/IP协议栈的实现细节就好了。
horace331 2004-07-29
  • 打赏
  • 举报
回复
to lostgdi731(O_O):
我这里所说的发送出去就是完整的进入下一个网络层。sendto 函数执行成功应该是证明数据从传输层到达了网络层,这个时候如果网络层的ARP协议能够将IP地址解析成MAC地址,就再次打包发给数据链路层。
我现在的实验结果是:如果一次所发数据大于1KB,那么sendto 函数会参照ARP的解析结果考虑是否要发送;否则,将数据直接发到网络层,由网络层判断。
lostgdi731 2004-07-29
  • 打赏
  • 举报
回复
我不同意的你看法:
“我想这个与配置无关,但我就觉得奇怪了,如果“但如果IP需要分片,则保证最后一片的发送,也就是最后一片是等到ARP解析完成后才发送的”,那你并不能解析那些机器的MAC,为什么也可以发出去呢?”

sendto 函数执行成功 证明 你的数据已发送到传输层,这点不一定说明你的数据已抵达目标机器。
同时,如果你发送的数据不太大的话函数执行所需的时间不会高的。
horace331 2004-07-28
  • 打赏
  • 举报
回复
是不是我比较笨所以电脑耍我?
horace331 2004-07-28
  • 打赏
  • 举报
回复
我运行结果如下:
Send Some Data To 192.168.0.1 1,Use Time:10 ms
Send Some Data To 192.168.0.1 2,Use Time:0 ms
Send Some Data To 192.168.0.1 3,Use Time:0 ms
Send Some Data To 192.168.0.1 4,Use Time:0 ms
Send Some Data To 192.168.0.1 5,Use Time:0 ms
Send Some Data To 192.168.0.1 6,Use Time:0 ms
Send Some Data To 192.168.0.1 7,Use Time:0 ms
Send Some Data To 192.168.0.1 8,Use Time:0 ms
Send Some Data To 192.168.0.1 9,Use Time:0 ms
Send Some Data Failed!
Send Some Data Failed!
Send Some Data Failed!
Send Some Data Failed!
Send Some Data Failed!
Send Some Data Failed!
Send Some Data Failed!
Send Some Data Failed!
Send Some Data Failed!
Send Some Data Failed!
Send Some Data To 192.168.0.120,Use Time:0 ms
Send Some Data Failed!
Send Some Data To 192.168.0.122,Use Time:0 ms
Send Some Data Failed!
Send Some Data Failed!
Send Some Data To 192.168.0.125,Use Time:0 ms
horace331 2004-07-28
  • 打赏
  • 举报
回复
我想这个与配置无关,但我就觉得奇怪了,如果“但如果IP需要分片,则保证最后一片的发送,也就是最后一片是等到ARP解析完成后才发送的”,那你并不能解析那些机器的MAC,为什么也可以发出去呢?
加载更多回复(26)

18,355

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧