ACE之旅——第一个ACE通讯程序
ACE最大的用处就是通讯了,这个就不多说了,模仿Stevens的UNP第一个实例——daytime服务器、客户端。
现从服务端svr.cpp开始,代码如下:
#include
"
ace/INET_Addr.h
"
#include
"
ace/SOCK_Stream.h
"
#include
"
ace/SOCK_Acceptor.h
"
#include
"
ace/Log_Msg.h
"
#include
<
time.h
>
int
ACE_TMAIN(
int
, ACE_TCHAR
*
[]) {
ACE_INET_Addr port_to_listen(
"
50000
"
);
ACE_SOCK_Acceptor acceptor;
if
(acceptor.open(port_to_listen,
1
)
==
-
1
)
ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT(
"
%p\n
"
), ACE_TEXT(
"
acceptor.open
"
)),
100
);
while
(
1
) {
ACE_SOCK_Stream peer;
ACE_INET_Addr peer_addr;
ACE_Time_Value timeout(
10
,
0
);
if
(acceptor.accept(peer,
&
peer_addr, NULL,
1
)
==
-
1
) {
if
(ACE_OS::last_error()
==
EINTR)
ACE_DEBUG((LM_DEBUG, ACE_TEXT(
"
(%P|%t) Interrupted while
"
),
ACE_TEXT(
"
waiting for connection\n
"
)));
}
else
{
ACE_TCHAR peer_name[MAXHOSTNAMELEN];
peer_addr.addr_to_string(peer_name, MAXHOSTNAMELEN);
ACE_DEBUG((LM_DEBUG, ACE_TEXT(
"
(%P|%t) Connectionfrom %s\n
"
), peer_name));
time_t ticks
=
time(NULL);
char
timeBuf[
128
];
memset(timeBuf,
0
,
sizeof
(timeBuf));
ACE_OS::snprintf(timeBuf,
sizeof
(timeBuf),
"
%.24s\r\n
"
, ctime(
&
ticks));
peer.send_n(timeBuf, ACE_OS::strlen(timeBuf));
peer.close();
}
}
return
0
;
}
学过socket的人应该不会有太大的困难,用原生的BSD socket API编写TCP服务端一般需要socket、bind、listen、accept等几个函数,使用到得数据结构struct sockaddr_in等,在ACE下,分别如下对应
· ACE的ACE_SOCK_Acceptor::open完成了sock,bind,listen这几个动作。
· ACE的ACE_SOCK_Acceptor::accept对应accept函数功能。
· ACE_SOCK_Stream对应原生socket API中accept返回的对端fd。
· ACE_INET_Addr对应struct sockaddr_in等结构。
只需知道这些类得基本功能、是做什么的,再通过几个小例子,结合官方doxygen生成的文档(http://www.dre.vanderbilt.edu/Doxygen/5.7.7/html/ace/index.html)查看某个类到底有哪些方法,ACE还是很好学的。
客户端代码cli.cpp如下:
#include
"
ace/INET_Addr.h
"
#include
"
ace/SOCK_Stream.h
"
#include
"
ace/SOCK_Connector.h
"
#include
"
ace/Log_Msg.h
"
int
ACE_TMAIN(
int
, ACE_TCHAR
*
[]) {
ACE_INET_Addr srvr(
50000
, ACE_LOCALHOST);
ACE_SOCK_Connector connector;
ACE_SOCK_Stream peer;
if
(connector.connect(peer, srvr)
==
-
1
)
ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT(
"
%p\n
"
), ACE_TEXT(
"
connect
"
)),
1
);
int
bc;
char
buf[
64
];
bc
=
peer.recv(buf,
sizeof
(buf));
write(
1
, buf, bc);
peer.close();
return
0
;
}
· ACE_SOCK_Connector::connect方法完成了原生socket API创建TCP客户端所需的socket、connect等函数的动作。
编译这两个程序的makefile如下:
CC= g++
INCL = $(ACE_ROOT)/include
LIBS = $(ACE_ROOT)/lib
cli_deps = cli.cpp
svr_deps = svr.cpp
.SUFFIXES: .cpp.o
.cpp.o:
$(CC) -g -I$(INCL) -c $*.cpp
all: cli svr
cli: $(cli_deps)
$(CC) -g -I$(INCL) -L$(LIBS) -o cli $(cli_deps) -lACE
svr: $(svr_deps)
$(CC) -g -I$(INCL) -L$(LIBS) -o svr $(svr_deps) -lACE
clean:
-rm *~
-rm cli
-rm svr
第一个使用ACE的socket通讯程序的实例,当然ACE远不止这些socket函数的封装之类的,接下来将使用ACE Reactor框架实现这个daytime程序。
(转载时请注明作者和出处。未经许可,请勿用于商业用途)
更多文章请访问我的Blog: http://www.cnblogs.com/logicbaby