biesange 发表于 2009-8-14 14:38:58

ace中数据分割问题,请高人指点

我是基于ACE类库做了一个UDP广播的发送和接收的例子,但是当发送的数据报大于1472字节时客户端就会接收不到。
我查了很多相关问题,据说是可以手动分片的 但是我不懂这方面的东西 有没有谁来指点一下?到底该如何分片,接收端该如何重组??
嘿嘿 先谢谢了~
代码如下:
sever.cpp
///
#include <ace/os.h>
#include <ace/Log_Msg.h>
#include <ace/INET_Addr.h>
#include <ace/SOCK_Dgram_Bcast.h>
#include <ace/Auto_Ptr.h>

int send_broadcast(ACE_INET_Addr& my_addr, u_short to_port, int time)
{
    static const u_short PORT = ACE_DEFAULT_SERVER_PORT;
char message;
memset(message,1,1485);
message = '\0';
sprintf(message,"%s%03d",message,time);
    ACE_DEBUG((LM_DEBUG,
      ACE_TEXT("Send data: %d%d\n"),
      strlen(message),time));
    ACE_SOCK_Dgram_Bcast udp(my_addr);
    ssize_t sent = udp.send(message,
                            ACE_OS_String::strlen(message) + 1,
                            to_port);
    udp.close();
    if (sent == -1)
      ACE_ERROR_RETURN((LM_ERROR,
ACE_TEXT("%p\n"),
ACE_TEXT("send")),
-1);
    return 0;
}
int ACE_TMAIN(int, ACE_TCHAR *[])
{
    ACE_INET_Addr my_addr;
    char hostname;
    ACE_OS::hostname(hostname, MAXHOSTNAMELEN);
    struct hostent* hptr;
    hptr = ACE_OS::gethostbyname(hostname); //gethostbyname·μ??ò??????òhostentêy?Y?á11μ?????
    char ip;
    char** pptr;
    switch(hptr->h_addrtype)
    {
    case AF_INET:
    case AF_INET6:
      pptr=hptr->h_addr_list;
      for(;*pptr!=NULL;pptr++)
      {
            printf("My address: %s\n", ACE_OS::inet_ntop(hptr->h_addrtype, *pptr, ip, sizeof(ip)));
            my_addr = ACE_INET_Addr(ACE_OS::inet_ntop(hptr->h_addrtype, *pptr, ip, sizeof(ip)));
      }
      break;
    default:
      printf("unknown address type\n");
      break;
    }
    int time = 100;
while(time>0)
{
send_broadcast(my_addr, 50000, time);
Sleep(200);
time--;
}   
    return 0;
}
client.cpp
///
#include <ace/os.h>
#include <ace/Log_Msg.h>
#include <ace/INET_Addr.h>
#include <ace/SOCK_Dgram_Bcast.h>
void echo_dgram()
{
    ACE_INET_Addr my_addr(ACE_static_cast(u_short, 50000));
    ACE_INET_Addr your_addr;
    ACE_SOCK_Dgram_Bcast udp(my_addr);
    char buff;
    size_t buflen = sizeof (buff);
    ssize_t recv_cnt = udp.recv(buff, buflen, your_addr);
    if (recv_cnt > 0)
    {
char numbuf;
numbuf = '\0';
sprintf(numbuf,"%04d%s\n",strlen(buff),&buff);
write(1, numbuf, strlen(numbuf));
      ssize_t sent = udp.send(buff, ACE_static_cast(size_t, buflen), your_addr);
    }
    udp.close();
    return;
}
int ACE_TMAIN(int, ACE_TCHAR *[])
{
    ACE_INET_Addr to(50000, ACE_LOCALHOST);
while(1)
{
echo_dgram();
}   
    return 0;
}

winston 发表于 2009-8-14 14:55:48

1480是一个典型的MTU值。加上UDP的包头等,实际你发的尺寸,还应该小一些。UDP不可靠,发大包不好用的。

biesange 发表于 2009-8-14 15:06:03

回复 #2 winston 的帖子

我知道,最多发1500,算上头的话一共1500,
所以实际数据是1472,
大于这个就要分包,
我想知道怎么分包啊。
我好可怜啊。
高手们指点一下吧。

wishel 发表于 2009-8-17 15:00:21

原帖由 biesange 于 2009-8-14 15:06 发表 http://acejoy.com/bbs/images/common/back.gif
我知道,最多发1500,算上头的话一共1500,
所以实际数据是1472,
大于这个就要分包,
我想知道怎么分包啊。
我好可怜啊。
高手们指点一下吧。

这种适应mtu的分包是ip做的,不用你操心。一般应用层做分包的目的是给udp增加可靠性(丢包请求补发,乱序重组等),而不是为了mtu。

感觉应该是你的程序的问题,你说的大于1472是都收不到,还是收不全,怎么验证的?
程序有很多地方不明白。例如:sprintf(numbuf,"%04d%s\n",strlen(buff),&buff);
这句是什么意思?

biesange 发表于 2009-8-17 17:59:01

斑竹救命啊

原帖由 wishel 于 2009-8-17 15:00 发表 http://www.acejoy.com/bbs/images/common/back.gif


这种适应mtu的分包是ip做的,不用你操心。一般应用层做分包的目的是给udp增加可靠性(丢包请求补发,乱序重组等),而不是为了mtu。

感觉应该是你的程序的问题,你说的大于1472是都收不到,还是收不全,怎么验证的?
程序有很多地 ...

sprintf(numbuf,"%04d%s\n",strlen(buff),&buff);
我在发送数据的时候,在最后3位加上了发送信息的id。
例如:
我设定的是100条,如果发送的信息为1500字节(message中字符串的大小加上28字节的附加信息),
去掉附加信息是1472字节(算上结束符),
如果收到了就会在客户端上打印出来。
打印结果是:
1472   100
1472    099
........
最新测试结果是:

win2003上开服务器,客户端可以正确接收,无论多大都可以。
winxp上开服务器,服务器发送超过1472字节就收不到。
这是什么原因呢。
如果用WpdPack_4_0_2检测,能够监测到所有的数据都分片了,
就是不知道为什么收不到。
win2003和winxp的设置不一样?
斑竹救命啊,明天就要出来了,折腾了2天都没有找到原因,我好可怜啊。

wishel 发表于 2009-8-18 19:27:52

收不到是指ssize_t recv_cnt = udp.recv(buff, buflen, your_addr);这句的revc_cnt为0么?
客户端是2003还是xp(可以换台主机看看,排除特殊主机问题的可能,也可以试试客户端和服务器都是xp的情况)?windows我不太熟悉,你用WpdPack_4_0_2检测的是发送方(服务器)的情况吧,这个软件能检测到接收端的收包情况么?
按lz现在的描述,2003发送就可以,xp上发送就有问题,如果能排除主机问题我也怀疑是不是这两个系统的协议栈实现有不同。
页: [1]
查看完整版本: ace中数据分割问题,请高人指点