这部分代码主要是基于ACE_wrappers/examples/Reactor/Proactor/test_udp_proactor.cpp
简化后,改部分代码在windows下的运行效果是:
工作在2000端口,监听udp报文并对udp报文进行处理,利用另外一台服务器向这台机器发送udp报文(利用flowtools发送netflow报文)可以得到如下的效果:
proactor.cpp:82:Receiver::open_addr called
handle_read_dgram called
handle_read_dgram called
handle_read_dgram called
handle_read_dgram called
handle_read_dgram called
handle_read_dgram called
handle_read_dgram called
一直继续下去
但是同样的代码在Linux下编译成功,却无法响应udp 报文
运行效果是:
./Proactor
Proactor.cpp:54:Receiver::open_addr called
(7704 | 1077249920) ACE_POSIX_AIOCB_Proactor::Max Number of AIOs=1024
然后就没有任何的效果了
怀疑问题可能是出在recv函数,也就是
rd_.recv (msg,
number_of_bytes_recvd,
0,
PF_INET,
this->act_);没有起作用
也有可能是linux下的ACE_POSIX_AIOCB_Proactor有问题,这是Proactor在linux下的默认构造
编译时候的选项如下:
g++ -I. -I. -Iinc/stlport -Ii
nc -g -O2 -c -o Proactor.o `test -f 'Proactor.cpp' || echo './'`Proactor.cpp
libtool --mode=link g++ -g -o2 -o Proactor -lACE -lstlport_gcc Proactor.o
编译选项时是否需要把thread给补充进去?
源代码如下:
// Proactor.cpp
#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"
//ACE_RCSID(Proactor, test_udp_proactor, "test_proactor.cpp,v 1.29 2001/02/02 23:41:16 shuston Exp")
#if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) || defined (ACE_HAS_AIO_CALLS)
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 sockDgram_;
ACE_Asynch_Read_Dgram rd_;
// rd (read dgram): for reading from a UDP socket.
const char* completion_key_;
const char* act_;
};
Receiver::Receiver (void)
: completion_key_ ("Receiver Completion Key"),
act_ ("Receiver ACT")
{
}
Receiver::~Receiver (void)
{
sockDgram_.close ();
}
int
Receiver::open_addr (const ACE_INET_Addr &localAddr)
{
ACE_DEBUG ((LM_DEBUG,
"%N:%l:Receiver::open_addr called/n"));
// Create a local UDP socket to receive datagrams.
if (this->sockDgram_.open (localAddr) == -1)
ACE_ERROR_RETURN ((LM_ERROR,
"%p/n",
"ACE_SOCK_Dgram::open"), -1);
// Initialize the asynchronous read.
if (this->rd_.open (*this,
this->sockDgram_.get_handle (),
this->completion_key_,
ACE_Proactor::instance ()) == -1)
ACE_ERROR_RETURN ((LM_ERROR,
"%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_);
return 0;
}
void
Receiver::handle_read_dgram (const ACE_Asynch_Read_Dgram::Result &result)
{
ACE_DEBUG ((LM_DEBUG,
"handle_read_dgram called/n"));
// ACE_Message_Block* msg = new ACE_Message_Block (1024);
//
// // create a message block to read the message body
// ACE_Message_Block* body =new ACE_Message_Block (1024);
// msg->cont (body);
//
// // ok lets do the asynch read
// size_t number_of_bytes_recvd = 1024;
//
// int res = rd_.recv (msg,
// number_of_bytes_recvd,
// 0,
// PF_INET,
// this->act_);
}
int
ACE_TMAIN (int argc, ACE_TCHAR *argv[])
{
Receiver receiver;
if (receiver.open_addr (ACE_INET_Addr (2000)) == -1)
return -1;
ACE_Proactor::instance() -> proactor_run_event_loop();
return 0;
}
#else /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS*/
int
ACE_TMAIN (int, ACE_TCHAR *[])
{
ACE_DEBUG ((LM_DEBUG,
"This example does not work on this platform./n"));
return 1;
}
#endif /* ACE_WIN32 && !ACE_HAS_WINCE || ACE_HAS_AIO_CALLS*/
问题点数:50、回复次数:3Top
a letter from Alexander Libman:
This example designed only for Windows.
Proactor I/O UDP functions are only declarative for UNIX.
POSIX aio_read/aio_write does not support UDP.
Moreover, POSIX aio is broken or not fully implemented on many POSIX platforms
including RedHat9.
If you have to port your Proactor application to POSIX/Linux,
I recommend you to use ACE- compatible Proactor from Terabit:
http://www.terabit.com.au
Details in : http://www.terabit.com.au/docs/Proactor2.htm
Download: http://www.terabit.com.au/Proactor541N.tar.gz
Top
2 楼darkstar21cn(≮天残≯无畏)(死亡进行时)回复于 2005-06-22 16:33:02 得分 25
sockDgram_.open ()调用失败了。