ACE_Proactor UDP(接收什么就打印什么)V1.0

下面的程序使用Proactor模式用UDP通信,由于UDP是无连接的,所以这里没有Connector和Acceptor

发送端发送一个复合消息,并打印发送的内容

接收端接收一个复合消息并打印接收到的内容

本例是对ACE自带的example的稍微修改了一下(打印发送和接收的内容,这样更加直观)

发送端:client_main.cpp

#include <vector>
#include <fstream>
#include <iterator>
#include <iostream>
#include <string>
using namespace std;
#include "ace/Reactor.h"
#include "ace/Message_Queue.h"
#include "ace/Asynch_IO.h"
#include "ace/OS.h"
#include "ace/Proactor.h"
#include "ace/Asynch_Connector.h"
#include <ace/SOCK_Dgram.h> 

//=============================================================================
/**
 *  @file    test_udp_proactor.cpp
 *
 *  $Id: test_udp_proactor.cpp 93639 2011-03-24 13:32:13Z johnnyw $
 *
 *  This program illustrates how the <ACE_Proactor> can be used to
 *  implement an application that does asynchronous operations using
 *  datagrams.
 *
 *
 *  @author Irfan Pyarali <[email protected]> and Roger Tragin <[email protected]>
 */
//=============================================================================

#include "ace/OS_NS_string.h"
#include "ace/OS_main.h"
#include "ace/Proactor.h"
#include "ace/Asynch_IO.h"
#include "ace/INET_Addr.h"
#include "ace/SOCK_Dgram.h"
#include "ace/Message_Block.h"
#include "ace/Get_Opt.h"
#include "ace/Log_Msg.h"

// Keep track of when we're done.
static int done = 0;

/**
 * @class Sender
 *
 * @brief The class will be created by <main>.
 */
class Sender : public ACE_Handler
{
public:
  Sender (void);
  ~Sender (void);

  //FUZZ: disable check_for_lack_ACE_OS
  ///FUZZ: enable check_for_lack_ACE_OS
  int open (const ACE_TCHAR *host, u_short port);

protected:
  // These methods are called by the freamwork

  /// This is called when asynchronous writes from the dgram socket
  /// complete
  virtual void handle_write_dgram (const ACE_Asynch_Write_Dgram::Result &result);

private:

  /// Network I/O handle
  ACE_SOCK_Dgram sock_dgram_;

  /// wd (write dgram): for writing to the socket
  ACE_Asynch_Write_Dgram wd_;

  const char* completion_key_;
  const char* act_;
};

Sender::Sender (void)
  : completion_key_ ("Sender completion key"),
    act_ ("Sender ACT")
{
}

Sender::~Sender (void)
{
  this->sock_dgram_.close ();
}

int
Sender::open (const ACE_TCHAR *host,
              u_short port)
{
  // Initialize stuff

  if (this->sock_dgram_.open (ACE_INET_Addr::sap_any) == -1)
    ACE_ERROR_RETURN ((LM_ERROR,
                       "[%D][line:%l]%p\n",
                       "ACE_SOCK_Dgram::open"), -1);

  // Initialize the asynchronous read.
  if (this->wd_.open (*this,
                      this->sock_dgram_.get_handle (),
                      this->completion_key_,
                      ACE_Proactor::instance ()) == -1)
    ACE_ERROR_RETURN ((LM_ERROR,
                       "[%D][line:%l]%p\n",
                       "ACE_Asynch_Write_Dgram::open"), -1);

  // We are using scatter/gather to send the message header and
  // message body using 2 buffers

  // create a message block for the message header
  ACE_Message_Block* msg = 0;
  ACE_NEW_RETURN (msg, ACE_Message_Block (100), -1);
  const char raw_msg [] = "To be or not to be.";
  // Copy buf into the Message_Block and update the wr_ptr ().
  msg->copy (raw_msg, ACE_OS::strlen (raw_msg) + 1);

  // create a message block for the message body
  ACE_Message_Block* body = 0;
  ACE_NEW_RETURN (body, ACE_Message_Block (100), -1);
  ACE_OS::memset (body->wr_ptr (), 'X', 100);
  body->wr_ptr (100); // always remember to update the wr_ptr ()

  // set body as the cont of msg.  This associates the 2 message blocks so
  // that a send will send the first block (which is the header) up to
  // length (), and use the cont () to get the next block to send.  You can
  // chain up to IOV_MAX message block using this method.
  msg->cont (body);

  // do the asynch send
  size_t number_of_bytes_sent = 0;
  ACE_INET_Addr serverAddr (port, host);
  int res = this->wd_.send (msg, number_of_bytes_sent, 0, serverAddr, this->act_);

  ACE_Message_Block* p = 0;
  p= msg;

  switch (res)
    {
    case 0:
      // this is a good error.  The proactor will call our handler when the
      // send has completed.
      break;
    case 1:
      // actually sent something, we will handle it in the handler callback
      ACE_DEBUG ((LM_DEBUG, "********************\n"));
      ACE_DEBUG ((LM_DEBUG,
                  "%s = %d\n",
                  "bytes sent immediately",
                  number_of_bytes_sent));

      while (p != NULL)
      {
          ACE_DEBUG ((LM_DEBUG,"YOU SEND[%s]\n",p->rd_ptr()));
          p = p->cont();
      }

      ACE_DEBUG ((LM_DEBUG, "********************\n"));
      res = 0;
      break;
    case -1:
      // Something else went wrong.
      ACE_ERROR ((LM_ERROR,
                  "[%D][line:%l]%p\n",
                  "ACE_Asynch_Write_Dgram::recv"));
      // the handler will not get called in this case so lets clean up our msg
      msg->release ();
      break;
    default:
      // Something undocumented really went wrong.
      ACE_ERROR ((LM_ERROR,
                  "[%D][line:%l]%p\n",
                  "ACE_Asynch_Write_Dgram::recv"));
      msg->release ();
      break;
    }
  return res;
}

void
Sender::handle_write_dgram (const ACE_Asynch_Write_Dgram::Result &result)
{
  ACE_DEBUG ((LM_DEBUG,
              "handle_write_dgram called\n"));

  ACE_DEBUG ((LM_DEBUG, "********************\n"));
  ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_to_write", result.bytes_to_write ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "handle", result.handle ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_transfered", result.bytes_transferred ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "flags", result.flags ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %s\n", "act", result.act ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "success", result.success ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %s\n", "completion_key", result.completion_key ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "error", result.error ()));
  ACE_DEBUG ((LM_DEBUG, "********************\n"));

  ACE_DEBUG ((LM_DEBUG,
              "Sender completed\n"));

  // No need for this message block anymore.
  result.message_block ()->release ();

  // Note that we are done with the test.
  done++;
}

int
ACE_TMAIN (int argc, ACE_TCHAR *argv[])
{

    //ACE_LOG_MSG->clr_flags(0);
    //ACE_LOG_MSG->set_flags(ACE_Log_Msg::STDERR | ACE_Log_Msg::VERBOSE);

    Sender sender;
    // Port that we're receiving connections on.
    u_short port = ACE_DEFAULT_SERVER_PORT;
    // Host that we're connecting to.
    string host("localhost");
    if (sender.open (host.c_str(), port) == -1)
    return -1;

    while (true)
    {
        ACE_Proactor::instance ()->handle_events ();
    }

    return 0;
}

接收端server_main.cpp

#include "ace/OS_NS_string.h"
#include "ace/OS_main.h"
#include "ace/Proactor.h"
#include "ace/Asynch_IO.h"
#include "ace/INET_Addr.h"
#include "ace/SOCK_Dgram.h"
#include "ace/Message_Block.h"
#include "ace/Get_Opt.h"
#include "ace/Log_Msg.h"

// Host that we're connecting to.
static ACE_TCHAR *host = 0;

// Port that we're receiving connections on.
static u_short port = ACE_DEFAULT_SERVER_PORT;

// Keep track of when we're done.
static int done = 0;

/**
 * @class Receiver
 *
 * @brief This class will receive data from
 * the network connection and dump it to a file.
 */
class Receiver : public ACE_Service_Handler
{
public:
  // = Initialization and termination.
  Receiver (void);
  ~Receiver (void);

  int open_addr (const ACE_INET_Addr &localAddr);

protected:
  // These methods are called by the framework

  /// This method will be called when an asynchronous read completes on
  /// a UDP socket.
  virtual void handle_read_dgram (const ACE_Asynch_Read_Dgram::Result &result);

private:
  ACE_SOCK_Dgram sock_dgram_;

  /// rd (read dgram): for reading from a UDP socket.
  ACE_Asynch_Read_Dgram rd_;
  const char* completion_key_;
  const char* act_;
};

Receiver::Receiver (void)
  : completion_key_ ("Receiver Completion Key"),
    act_ ("Receiver ACT")
{
}

Receiver::~Receiver (void)
{
  sock_dgram_.close ();
}

int
Receiver::open_addr (const ACE_INET_Addr &localAddr)
{
  ACE_DEBUG ((LM_DEBUG,
              "[%D][line:%l]Receiver::open_addr called\n"));

  // Create a local UDP socket to receive datagrams.
  if (this->sock_dgram_.open (localAddr) == -1)
    ACE_ERROR_RETURN ((LM_ERROR,
                       "[%D][line:%l]%p\n",
                       "ACE_SOCK_Dgram::open"), -1);

  // Initialize the asynchronous read.
  if (this->rd_.open (*this,
                      this->sock_dgram_.get_handle (),
                      this->completion_key_,
                      ACE_Proactor::instance ()) == -1)
    ACE_ERROR_RETURN ((LM_ERROR,
                       "[%D][line:%l]%p\n",
                       "ACE_Asynch_Read_Dgram::open"), -1);

  // Create a buffer to read into.  We are using scatter/gather to
  // read the message header and message body into 2 buffers

  // create a message block to read the message header
  ACE_Message_Block* msg = 0;
  ACE_NEW_RETURN (msg, ACE_Message_Block (1024), -1);

  // the next line sets the size of the header, even though we
  // allocated a the message block of 1k, by setting the size to 20
  // bytes then the first 20 bytes of the reveived datagram will be
  // put into this message block.
  msg->size (20); // size of header to read is 20 bytes

  // create a message block to read the message body
  ACE_Message_Block* body = 0;
  ACE_NEW_RETURN (body, ACE_Message_Block (1024), -1);
  // The message body will not exceed 1024 bytes, at least not in this test.

  // set body as the cont of msg.  This associates the 2 message
  // blocks so that a read will fill the first block (which is the
  // header) up to size (), and use the cont () block for the rest of
  // the data.  You can chain up to IOV_MAX message block using this
  // method.
  msg->cont (body);

  // ok lets do the asynch read
  size_t number_of_bytes_recvd = 0;

  int res = rd_.recv (msg,
                      number_of_bytes_recvd,
                      0,
                      PF_INET,
                      this->act_);
  switch (res)
    {
    case 0:
      // this is a good error.  The proactor will call our handler when the
      // read has completed.
      break;
    case 1:
      // actually read something, we will handle it in the handler callback
      ACE_DEBUG ((LM_DEBUG, "********************\n"));
      ACE_DEBUG ((LM_DEBUG,
                  "%s = %d\n",
                  "bytes recieved immediately",
                  number_of_bytes_recvd));

      ACE_DEBUG ((LM_DEBUG, "********************\n"));
      res = 0;
      break;
    case -1:
      // Something else went wrong.
      ACE_ERROR ((LM_ERROR,
                  "[%D][line:%l]%p\n",
                  "ACE_Asynch_Read_Dgram::recv"));
      // the handler will not get called in this case so lets clean up our msg
      msg->release ();
      break;
    default:
      // Something undocumented really went wrong.
      ACE_ERROR ((LM_ERROR,
                  "[%D][line:%l]%p\n",
                  "ACE_Asynch_Read_Dgram::recv"));
      msg->release ();
      break;
    }

  return res;
}

void
Receiver::handle_read_dgram (const ACE_Asynch_Read_Dgram::Result &result)
{
  ACE_DEBUG ((LM_DEBUG,
              "handle_read_dgram called\n"));

  ACE_DEBUG ((LM_DEBUG, "********************\n"));
  ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_to_read", result.bytes_to_read ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "handle", result.handle ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "bytes_transfered", result.bytes_transferred ()));
  ACE_INET_Addr peerAddr;
  result.remote_address (peerAddr);
  ACE_DEBUG ((LM_DEBUG, "%s = %s:%d\n", "peer_address", peerAddr.get_host_addr (), peerAddr.get_port_number ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "flags", result.flags ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %s\n", "act", result.act ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "success", result.success ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %s\n", "completion_key", result.completion_key ()));
  ACE_DEBUG ((LM_DEBUG, "%s = %d\n", "error", result.error ()));
  ACE_DEBUG ((LM_DEBUG, "********************\n"));

  if (result.success () && result.bytes_transferred () != 0)
    {
      // loop through our message block and print out the contents
      for (const ACE_Message_Block* msg = result.message_block (); msg != 0; msg = msg->cont ())
        { // use msg->length () to get the number of bytes written to the message
          // block.
          ACE_DEBUG ((LM_DEBUG, "Buf=[size=<%d>", msg->length ()));
          for (u_long i = 0; i < msg->length (); ++i)
            ACE_DEBUG ((LM_DEBUG,
                        "%c", (msg->rd_ptr ())[i]));
          ACE_DEBUG ((LM_DEBUG, "]\n"));
        }
    }

  ACE_DEBUG ((LM_DEBUG,
              "Receiver completed\n"));

  // No need for this message block anymore.
  result.message_block ()->release ();

  // Note that we are done with the test.
  done++;
}

int
    ACE_TMAIN (int argc, ACE_TCHAR *argv[])
{

    //ACE_LOG_MSG->set_flags(ACE_Log_Msg::STDERR | ACE_Log_Msg::VERBOSE);

    Receiver receiver;

    if (receiver.open_addr (ACE_INET_Addr (port)) == -1)
        return -1;

    while (true)
    {
        ACE_Proactor::instance ()->handle_events ();
    }

    return 0;
}

先运行接收端,再运行发送端,你懂的。

发送端程序运行结果:

接收端运行结果:

时间: 2024-10-08 18:36:24

ACE_Proactor UDP(接收什么就打印什么)V1.0的相关文章

xcode中的udp接收数据

1.udpclient的初始化 udpClient=[[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:mainQueue]; udpClient.delegate=self; NSError *err; BOOL bret=[udpClient bindToPort:8009 error:&err];  //绑定接收数据用的端口 BOOL ret=[udpClient beginReceiving:&err ];

气瓶安全云充装V1.0.201604

    气瓶安全云平台     充装需求说明书     Ver:1.0 无锡乾元智能安全技术研究有限公司 更新日期:2016.04 目   录 第一部分 项目概述... 4 1.1背景.备注... 4 1.2关键词.术语解释... 4 1.3项目描述... 4 1.4保密与版权声明... 5 第二部分 项目详细要求... 5 2.1项目功能.性能要求... 5 2.2性能要求... 6 2.3登陆与注册... 8 2.3.1 登录... 8 2.3.2 注册... 8 2.4菜单功能... 10

安卓开发开发规范手册V1.0

安卓开发开发规范手册V1.0 之前发布过一份Web安全开发规范手册V1.0,看到收藏文章的读者挺多,发现整理这些文档还挺有意义. 最近周末抽了些时间把之前收集关于安卓安全开发的资料也整理了一下,整理出一份安卓安全开发手册,大部分内容都是在一些博客看到各位师傅的分享. 一.manifest文件安全 1.1 禁止PermissionGroup的属性为空 PermissionGroup可以对permission进行一个逻辑上的分组.如果PermissionGroup的属性为空,会导致权限定义无效,且其

heatmap.js v1.0 到 v2.0,详细总结一下:)

前段时间,项目要开发热力图插件,研究了heatmap.js,打算好好总结一下. 本文主要有以下几部分内容: 部分源码理解 如何迁移到v2.0 v2.0官方文档译文 关于heatmap.js介绍,请看这里: http://www.oschina.net/p/heatmap-js 目前,对于热力图的开发,百度.高德开发平台上使用的都是这款JS开源库.当然,现在还有我们公司:P 百度示例:http://developer.baidu.com/map/jsdemo.htm#c1_15 高德示例:http

QT-利用C++仿制windown自带的记事本程序V1.0

下班无事, 发现QT还是很好用的, 就仿制windows的记事本做了一个,未彻底DEBUG, 先拿来分享下. windows记事本大概是这样的: 大概分为以下几步: 1. 界面用QT代码写,即可, QT的布局很强大 1 //create all actions 2 void Notepad::createActions() 3 { 4 newAct = new QAction(tr("新建(&N)"), this); 5 openAct = new QAction(tr(&qu

_00024 尼娜抹微笑伊拉克_云计算ClouderaManager以及CHD5.1.0群集部署安装文档V1.0

笔者博文:妳那伊抹微笑 itdog8 地址链接 : http://www.itdog8.com(个人链接) 博客地址:http://blog.csdn.net/u012185296 博文标题:_00024 妳那伊抹微笑_云计算之ClouderaManager以及CHD5.1.0集群部署安装文档V1.0 个性签名:世界上最遥远的距离不是天涯,也不是海角.而是我站在妳的面前.妳却感觉不到我的存在 技术方向:Flume+Kafka+Storm+Redis/Hbase+Hadoop+Hive+Mahou

基于apache和mysql,安装seafile - v1.0

seafile:下一代的开源云存储更好的文件同步,隐私保护和团队协作功能!本文基于官方文档,补充描述基于apache和mysql,安装seafile服务器. 原文网址:https://cloud.seafile.com/group/762/wiki/%E5%9C%A8apache%E7%8E%AF%E5%A2%83%E4%B8%8B%E9%83%A8%E7%BD%B2seafile/ 修改:陈海青(http://hhrz.org) 1.准备 下载安装预装了apache和mysql的虚拟机(基于d

Chasm Consulting PumpSim v1.0.3.2 1CD管网和泵送系统可视化设计仿真

Chasm Consulting PumpSim v1.0.3.2 1CD管网和泵送系统可视化设计仿真PumpSim提供了一个完整的三维动态环境下,生成从您的网络中最精确的模拟抽水和数据.无限期全功能授权,官网售价高达$2,995美元.使用PumpSim软件:轻松地构建管模式在真正的大型3D.估计最佳管道尺寸.建模和仿真流量,压力和泵的性能.导入设计和固体从AutoCAD(DXF).Pumpsim 是为了提供设计管网和泵送系统的详细可视化仿真.使用Pumpsim可以建模:管道和泵压流动的数量和速

Android编程规范V1.0

转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992 本文章是根据众多公司的编程规范整理而成,如果错误,还请指出. Android编程规范 编写人 赵凯强 日期 2014-8-5 审核人   日期   批准人   日期     修改记录(REVISION CHART) 版本 作者 修改描述 修改日期 1.0 赵凯强 初稿 2014-8-5     1.概述 1.1目的与概述 本文提供一整套编写高效可靠的android代码的标准.约定和指南.它们以安全可靠的软

_00024 妳那伊抹微笑_云计算之ClouderaManager以及CHD5.1.0集群部署安装文档V1.0

博文作者:妳那伊抹微笑 博客地址:http://blog.csdn.net/u012185296 博文标题:_00024 妳那伊抹微笑_云计算之ClouderaManager以及CHD5.1.0集群部署安装文档V1.0 个性签名:世界上最遥远的距离不是天涯,也不是海角,而是我站在妳的面前,妳却感觉不到我的存在 技术方向:Flume+Kafka+Storm+Redis/Hbase+Hadoop+Hive+Mahout+Spark ... 云计算技术 转载声明:可以转载, 但必须以超链接形式标明文章