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

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

[C#参考]利用Socket连续发送数据

这个例子只是一个简单的连续发送数据,接收数据的DEMO.因为最近做一个项目,要求robot连续的通过Socket传回自己的当前的位置坐标,然后客户端接收到坐标信息,在本地绘制地图,实时显示robot的位置. 里面还有好多的问题,在实际的项目中一定要解决,不然肯定跑步起来.比如:消息边界问题(帧的边界).消息命令的解析等 下面直接代码: 服务器的代码: using System; using System.Collections.Generic; using System.Linq; using

ACE中UDP通信

转载于:http://www.cnblogs.com/TianFang/archive/2006/12/07/585205.html udp是一种无连接的协议,提供无连接不可靠的服务. 在ace中,通过ACE_SOCK_Dgram类提供udp通信服务,ACE_SOCK_Dgram和ACE_SOCK_Stream的API非常类似,一样提供了send,recv及close等常用操作,这里就不再累述了. udp通信时无需像tcp那样建立连接和关闭连接,tcp编程时需要通过accept和connect来

【Android开发—智能家居系列】(四):UDP通信发送指令

思路回顾 [1]手机连接WIFI模块 [2]UDP通信对WIFI模块发送指令,以和WIFI模块保持连接状态 [3]UDP通信对WIFI模块发送指令,让其搜索可用的无线网,返回WIFI列表 [4]发送指令,让WIFI模块接入指定路由 [5]手机连接路由 [6]发送指令,获得WIFI模块的动态IP地址 UDP通信线程类 package com.jczb.smartlife.common; import java.io.IOException; import java.net.DatagramPack

[python] 网络编程之套接字Socket、TCP和UDP通信实例

很早以前研究过C#和C++的网络通信,参考我的文章: C#网络编程之Tcp实现客户端和服务器聊天 C#网络编程之套接字编程基础知识 C#网络编程之使用Socket类Send.Receive方法的同步通讯 Python网络编程也类似.同时最近找工作笔试面试考察Socket套接字.TCP\UDP区别比较多,所以这篇文章主要精简了<Python核心编程(第二版)>第16章内容.内容包括:服务器和客户端架构.套接字Socket.TCP\UDP通信实例和常见笔试考题. 最后希望文章对你有所帮助,如果有不

python实现TCP/UDP通信

一.说明 对于TCP/udp的说明已经很多了,我在这里只是简单的说明一下 二.套接字scoket 套接字是一种具有之前所说的"通信端点"概念的计算网络数据结构.相当 于电话插口,没它无法通信,这个比喻非常形象.        套接字起源于20世纪70年代加州伯克利分校版本的Unix,即BSD Unix .又称为"伯克利套接字"或"BSD套接字".最初套接字被设计用在同一台 主机上多个应用程序之间的通讯,这被称为进程间通讯或IPC.       

JAVA网络编程--UDP通信

首先网络传输数据需了解例如以下三点 1.找到对方IP 2.数据要发送到对方指定的应用程序上,为了标识这些应用程序,所以给这些网络应用程序用数字进行了标识.为了方便称呼这个数字,叫做port,逻辑port 3.  定义通信规则.这个通信规则称为协议. 国际组织定义了通用协议TCP/IP. 127.0.0.1本机回环地址 不易记忆,可用主机名 主机名:localhost 0-65535port范围 0-1024系统使用或保留port .当中mysql的port号为 3306 一.UDP UDP相对于

Android 之简单UDP通信

一 Android UDP通信编程步骤 服务器端: 1.建立Socket 2.监听端口  3.接收数据  4.实现数据发送 客户端:直接实现数据发送即可 二 代码,实现一个简单的UdpHelper类 1 package com.br.delphi.centercontrol; 2 3 import android.os.Handler; 4 import android.os.Message; 5 import android.util.Log; 6 7 import java.io.IOExc

高性能 TCP &amp; UDP 通信框架 HP-Socket v3.2.2 正式发布

HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#.Delphi.E(易语言).Java.Python 等编程语言接口.HP-Socket 对通信层实现完全封装,应用程序不必关注通信层的任何细节:HP-Socket 提供基于事件通知模型的 API 接口,能非常简单高效地整合到新旧应用程序中. 为了让使用者能方便快速地学习和使用 HP-Socket,迅速掌握

高性能 TCP &amp; UDP 通信框架 HP-Socket v3.3.1 正式发布

HP-Socket 是一套通用的高性能 TCP/UDP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C++.C#.Delphi.E(易语言).Java.Python 等编程语言接口.HP-Socket 对通信层实现完全封装,应用程序不必关注通信层的任何细节:HP-Socket 提供基于事件通知模型的 API 接口,能非常简单高效地整合到新旧应用程序中. 为了让使用者能方便快速地学习和使用 HP-Socket,迅速掌握