首页 > 代码库 > ACE基本的UDP通信(二)连续发送和连续接收 1.0

ACE基本的UDP通信(二)连续发送和连续接收 1.0

这里对UDP进行了封装,封装出了一个UDPSender、一个UDPReceiver。

UDPSender和UDPReceiver被封装在一个DLL中。

双方由于不需要建立连接的过程,所以一个就连续发送,一个连续接收。

由于接收不过来就会丢包,所以发送速度是接收速度的1/2来缓解接收压力

(其中一次测试,发送10001个,接收到了9860个,之所以丢包就是因为sender和receiver每次动作sleep的时间一样短,改成sender sleep(2time),receiver sleep(1time)就不丢数据了。)


test_UDPSender_main.cpp

#ifndef UDP_H
#include "UDP.h"
#endif

#include <string>
using namespace std;

#include "ace/OS.h"
#include "ace/Message_Block.h"
#include "ace/Service_Config.h"
#include "ace/Reactor.h"

int ACE_TMAIN (int argc, ACE_TCHAR *argv[]) 
{
    if (ACE_Service_Config::open(argc,argv,
        ACE_DEFAULT_LOGGER_KEY,1,0,1) < 0)
    {
        ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("%p/n"), ACE_TEXT("Service Config open")), -1);
    }


    ACE_Message_Block* mb = new ACE_Message_Block(5000);
    string str("carea");
    for (int i=0;i<1000;++i)
    {
        mb->copy(str.c_str(),str.size());

    }
    int i = 0;

    while (true)
    {
        //这里对象应该在循环外部创建以提高效率,而不用每次都创建临时对象发送,
        //之所以放到这里是看看临时对象在释放会不会正常释放资源,经过测试是可以的
        ACE_INET_Addr remote_addr("localhost:1032");
        UDPSender udp_sender(1048);

        int length = udp_sender.send_udp(mb->rd_ptr(),mb->length(),remote_addr);

        if (length>0)
        {
            ACE_DEBUG((LM_DEBUG,"OK,send[%d] successed\n",
                ++i));
            ACE_OS::sleep(ACE_Time_Value(0,20000));
            if (i>1000)
            {
                break;
            }
        }
        else
        {
            ACE_DEBUG((LM_ERROR,"NO,send failed\n"));
            break;
        }
    }
    

    mb->release();

    ACE_Reactor::instance()->run_reactor_event_loop();

    return 0;
};
发送端发完了全部的包,每个发送对象发送完毕之后在析构的时候close socket



test_UDPReceiver_main.cpp

#ifndef UDP_H
#include "UDP.h"
#endif

#include "ace/OS.h"
#include "ace/Reactor.h"
#include "ace/Service_Config.h"

int ACE_TMAIN (int argc, ACE_TCHAR *argv[]) 
{
    if (ACE_Service_Config::open(argc,argv,
        ACE_DEFAULT_LOGGER_KEY,1,0,1) < 0)
    {
        ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("%p/n"), ACE_TEXT("Service Config open")), -1);
    }

    char arr[10001]={0};
    UDPReceiver udp_receiver(1032);
    ACE_INET_Addr remote_addr("localhost:1048");
    int i = 0;
    while (true)
    {

        int length = udp_receiver.receive_udp(arr,sizeof(arr),remote_addr);

        if (length>0)
        {
            ACE_DEBUG((LM_DEBUG,"OK,receive th %ds successed\n",
                ++i));
            ACE_OS::sleep(ACE_Time_Value(0,10000));
        }
        else
        {
            ACE_DEBUG((LM_ERROR,"NO,receive failed\n"));
            break;
        }
    }
    
    ACE_Reactor::instance()->run_reactor_event_loop();


    return 0;
};
接收端收到了全部的包


封装DLL所需的文件

头文件SCP_Export.h

#ifndef SCP_EXPORT_H
#define SCP_EXPORT_H

     #ifdef WIN32       //for windows
         #ifdef SCP_EXPORTS           //for windows generate dll,you have to define SCP_EXPORTS in your preprocessor
         #define SCP_Export __declspec(dllexport)       
         #else      
         #define SCP_Export           //for windows as source file
         #endif
     #else             //for Linux
         #ifdef SCP_EXPORTS           //for Linux as source file          
         #define SCP_Export     
         #else 
         #define SCP_Export           //for Linux generate dll
         #endif
     #endif

#endif

头文件UDP.h

#ifndef UDP_H
#define UDP_H

#include "ace/INET_Addr.h"
#include "ace/SOCK_Dgram.h"
#include "ace/Message_Block.h"
#include "ace/Log_Msg.h"
#include "ace/SOCK_Dgram_Bcast.h"

#include <string>
using std::string;

#ifndef SCP_EXPORT_H
#include "SCP_Export.h"
#endif

class SCP_Export UDP 
{
public:
    explicit UDP(u_short local_port);
    ~UDP();
protected:
    ACE_INET_Addr local_port_addr_;
    ACE_SOCK_Dgram peer_;    //本地地址藏匿于此,发送的时候除了知道目的地址,也要携带本地地址的(因为UDP没有连接这一说)
};

class SCP_Export UDPSender : public UDP
{
public:
    UDPSender(u_short port_number);
    int send_udp (const void* message,const int length,const ACE_INET_Addr& remote_addr);
};

class SCP_Export UDPReceiver : public UDP
{
public:
    //在指定端口接收UDP报文
    explicit UDPReceiver(u_short port_number);
    //返回receive_length == -1 表示未接收到,
    //接收内容放到mb中,
    //对方地址在remote_addr
    int receive_udp(char* buffer,const int buffer_length,ACE_INET_Addr& remote_addr);
};

#endif
源文件UDP.cpp

#include "UDP.h"

UDP::UDP(u_short local_port)
    :local_port_addr_(local_port),peer_(local_port_addr_)
{
    ACE_DEBUG((LM_INFO,"UDP(%d)\n",local_port));
}

UDP::~UDP()
{
    ACE_DEBUG((LM_INFO,"~UDP() socket closed.\n"));
    this->peer_.close();
}

UDPSender::UDPSender(u_short port_number)
    :UDP(port_number)
{
}

int UDPSender::send_udp (const void* message,const int length,const ACE_INET_Addr& remote_addr)
{
    int send_bytes = this->peer_.send(message,length,remote_addr);

    if (send_bytes == -1)
    {
        ACE_ERROR((LM_ERROR,
            ACE_TEXT("(%P|%t) UDP send to %s %p\n"),
            remote_addr.get_host_addr(),
            ACE_TEXT ("failed")));
    }
    return send_bytes;
}

UDPReceiver::UDPReceiver(u_short port_number)
    :UDP(port_number)
{
    ACE_DEBUG((LM_INFO,"UDPReceiver(%d)\n",port_number));
}

int UDPReceiver::receive_udp(char* buffer,const int buffer_length,ACE_INET_Addr& remote_addr)
{
    int receive_length = peer_.recv(buffer,buffer_length,remote_addr);    //接收消息,获取远程地址信息
    if (receive_length != -1)
    {
        string str(buffer,buffer_length);
        ACE_DEBUG((LM_DEBUG,"UDPReceiver receive length[%d]\n",
            receive_length));
    }
    else
    {
        ACE_DEBUG((LM_ERROR,"UDPReceiver::receive_udp failed\n"));
    }

    return receive_length;
}










ACE基本的UDP通信(二)连续发送和连续接收 1.0