这里对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; }
时间: 2024-10-08 18:04:31