求助ACE中ACE_Acceptor下函数peer().recv_n接收不到数据
为什么在客户端给服务器端发信息的时候,服务器端的handle_input(ACE_HANDLE)函数被调用后,函数中的this->peer().recv_n(data,DATA_SIZE))中是收不到数据?而且handle_input被调用了两次,这是为什么。请哪位大哥解答,谢谢了。小弟在线等!服务器端代码:
#include "ace/Reactor.h"
#include "ace/Svc_Handler.h"
#include "ace/Acceptor.h"
#include "ace/Synch.h"
#include "ace/SOCK_Acceptor.h"
#include <iostream>
#define PORT_NUM 19999
#define DATA_SIZE 13
class My_Svc_Handler;
typedef ACE_Acceptor <My_Svc_Handler,ACE_SOCK_ACCEPTOR>MyAcceptor;
class My_Svc_Handler:public ACE_Svc_Handler <ACE_SOCK_STREAM,ACE_NULL_SYNCH>
{
public:
My_Svc_Handler()
{
data= new char;
}
int open(void*)
{
std::cout < <"Connection established" < <std::endl;
ACE_Reactor::instance()->register_handler(this, ACE_Event_Handler::READ_MASK);
return 0;
}
int handle_input(ACE_HANDLE)
{
int byteCount = 0;
if ( (byteCount = this->peer().recv_n(data,DATA_SIZE)) == -1)
{
ACE_OS::printf(" < < Error!\n");
}
else
{
data = 0;
ACE_OS::printf(" < < %s\n",data);
}
return 0;
}
private:
char* data;
};
int main(int argc, char* argv[])
{
ACE_INET_Addr addr(PORT_NUM);
MyAcceptor acceptor(addr,ACE_Reactor::instance());
while(1)
{
ACE_Reactor::instance()->handle_events();
}
return 0;
}
客户端代码:
#include "ace/SOCK_Connector.h"
#include "ace/OS.h"
#include "ace/Log_Msg.h"
class Client
{
public:
Client( char *addr, int port )
:remoteAddr_( port, addr )
{
}
int ConnectToServer()
{
if ( connector_.connect( clientStream_, remoteAddr_ ) == -1)
{
ACE_ERROR_RETURN ((LM_ERROR,"(%P|%t) %p\n","connection failed"),-1);
}
else
{
ACE_DEBUG ((LM_DEBUG,"(%P|%t) connected to %s\n",remoteAddr_.get_host_name()));
}
return 0;
}
int SendToServer()
{
char *buf = "Hello world!";
if( clientStream_.send_n( buf, ACE_OS::strlen(buf)+1, 0 ) != -1 )
{
ACE_DEBUG( (LM_DEBUG,"Send %s to server succeed!\n", buf) );
}
else
{
ACE_DEBUG( (LM_DEBUG,"Send %s to server failed!\n", buf) );
}
return 0;
}
private:
ACE_INET_Addr remoteAddr_;
ACE_SOCK_Connector connector_;
ACE_SOCK_Stream clientStream_;
};
int main( int argc, char *argv[] )
{
char *remoteAddr = "127.0.0.1";
intport = 19999;
Client client( remoteAddr, port );
client.ConnectToServer();
client.SendToServer();
return 0;
};
编译环境为windows xp.编译工具为visual c++ 2003.ACE版本包为ACE+TAO+CIAO-5.6.9
[ 本帖最后由 pengxiqin 于 2009-10-20 21:58 编辑 ] 1.收不到是一个什么概念?收不全还是recv返回-1了?最好提供一些详细的运行期信息。
2.handle_input被调用了两次,描述的太笼统了,把堆栈信息贴出来看看先。 原因:client发送完后立刻退出了,发送成功返回只是表示数据已经发到socket buffer里了,但不一定发到对端。如果立即退出进程,系统会自动调用close,buffer里的数据被丢弃了,只向server发送一个fin包。(这种情况可能不同的系统有不同的实现行为,而且跟so_linger的设置有关)
所以在Client::SendToServer()的ruturn前加一句:ACE_OS::sleep(1);就可以了。
另外My_Svc_Handler::handle_input()中的处理也有问题,没有考虑client退出连接的情况。 #include "ace/Reactor.h"
#include "ace/Svc_Handler.h"
#include "ace/Acceptor.h"
#include "ace/Synch.h"
#include "ace/SOCK_Acceptor.h"
#include "ace/SOCK_Connector.h"
#include "ace/OS.h"
#include "ace/Log_Msg.h"
#include <iostream>
#define PORT_NUM 19999
#define DATA_SIZE 13
class My_Svc_Handler;
typedef ACE_Acceptor <My_Svc_Handler,ACE_SOCK_Acceptor>MyAcceptor;
class My_Svc_Handler:public ACE_Svc_Handler <ACE_SOCK_STREAM,ACE_NULL_SYNCH>
{
public:
My_Svc_Handler()
{
data= new char;
}
int open(void*)
{
std::cout <<"Connection established" <<std::endl;
return ACE_Svc_Handler <ACE_SOCK_STREAM,ACE_NULL_SYNCH>::open();
}
int handle_input(ACE_HANDLE)
{
int byteCount = 0;
if ( (byteCount = this->peer().recv_n(data,DATA_SIZE)) == -1)
{
ACE_OS::printf(" << Error!\n");
}
else if (byteCount == 0) {
ACE_OS::printf(" client disconnected!\n");
return -1;
}
else {
data = 0;
ACE_OS::printf(" << %s\n",data);
}
return 0;
}
int handle_close(ACE_HANDLE, ACE_Reactor_Mask) {
ACE_OS::printf("handle_close() called!\n");
delete[] data;
return 0;
}
private:
char* data;
};
int main(int argc, char* argv[])
{
ACE_INET_Addr addr(PORT_NUM);
MyAcceptor acceptor(addr,ACE_Reactor::instance());
ACE_Reactor::instance()->run_event_loop();
return 0;
}
class Client
{
public:
Client( char *addr, int port )
:remoteAddr_( port, addr )
{
}
int ConnectToServer()
{
if ( connector_.connect( clientStream_, remoteAddr_ ) == -1)
{
ACE_ERROR_RETURN ((LM_ERROR,"(%P|%t) %p\n","connection failed"),-1);
}
else
{
ACE_DEBUG ((LM_DEBUG,"(%P|%t) connected to %s\n",remoteAddr_.get_host_name()));
}
return 0;
}
int SendToServer()
{
char *buf = "Hello world!";
if( clientStream_.send_n( buf, ACE_OS::strlen(buf)+1, 0 ) != -1 )
{
ACE_DEBUG( (LM_DEBUG,"Send %s to server succeed!\n", buf) );
}
else
{
ACE_DEBUG( (LM_DEBUG,"Send %s to server failed!\n", buf) );
}
//ACE_OS::sleep(1);
clientStream_.close();
return 0;
}
private:
ACE_INET_Addr remoteAddr_;
ACE_SOCK_Connector connector_;
ACE_SOCK_Stream clientStream_;
};
int main_client( int argc, char *argv[] )
{
char *remoteAddr = "127.0.0.1";
intport = 19999;
Client client( remoteAddr, port );
client.ConnectToServer();
client.SendToServer();
return 0;
};
[ 本帖最后由 wishel 于 2009-10-23 16:28 编辑 ] 更好的办法是用clientStream_.close();代替ACE_OS::sleep(1)
这样用比较温和的方式关闭socket,而不是进程结束交给os强行关闭。残留在socket buffer中的数据仍然会发送出去。
回复 #5 wishel 的帖子
谢谢版主,辛苦了,我调试到后来也想到这个问题了。小弟刚开始学习ACE,请多指教,谢谢回复 #5 wishel 的帖子
请问版主,为什么在class My_Svc_Handler中的函数int handle_close(ACE_HANDLE, ACE_Reactor_Mask) {
ACE_OS::printf("handle_close() called!\n");
delete[] data;
return 0;
}
释放内存失败呢?谢谢楼主,望得到你的指导,谢谢! 原帖由 pengxiqin 于 2009-10-27 00:31 发表 http://www.acejoy.com/bbs/images/common/back.gif
请问版主,为什么在class My_Svc_Handler中的函数
int handle_close(ACE_HANDLE, ACE_Reactor_Mask) {
ACE_OS::printf("handle_close() called!\n");
delete[] data;
return...
我运行的时候没问题的啊。释放失败后是什么表现呢?异常退出还是打印了出错信息?
回复 #8 wishel 的帖子
弹出一个异常窗口报告如下错误:我在很多释放内存的地方都碰到这种错误,不知道为什么?
我的操作系统是:Microsoft Windows XP Professional 版本2002 Service Pack2
编译器是vc 2003
[ 本帖最后由 pengxiqin 于 2009-10-28 00:51 编辑 ] 不知道你改了我发的程序没。这么简单的new[] + delete[],应该不会出问题。
你可以测下:
data= new char;
delete[] data;
如果出问题就是系统问题了。
页:
[1]
2