完善接口功能,添加网络示例

This commit is contained in:
zsxxsz 2014-07-29 21:48:23 +08:00
parent 79e18cc2e9
commit 54aa697c22
20 changed files with 248 additions and 25 deletions

View File

@ -1,5 +1,12 @@
修改历史列表:
------------------------------------------------------------------------
247) 2014.7.29
247.1) feature: socket_stream 类增加了 alive() 方法用来检测网络连接的存活态
247.2) feature: stream 类扩展了 set_ctx/get_ctx 方法,可以通过 key 设置/查找
其对应的 ctx 对象,同时增加了 del_ctx 方法用来删除 key 对应的 ctx 对象
247.3) samples: 增加了 socket/client, socket/server 两个网络测试用例,用来测试
网络关闭时第一次写依然会成功的情况
246) 2014.7.24
246.1) bugfix: http_request.cpp 中调用方法 write_head 时,若请求方法为 POST 方法,
则增加了有效的重试机制

View File

@ -134,6 +134,13 @@ public:
*/
bool set_local(const char* addr);
/**
* (使)
* @return {bool} false
* true
*/
bool alive() const;
/////////////////////////////////////////////////////////////////////
void close_ssl(void);

View File

@ -1,5 +1,7 @@
#pragma once
#include "acl_cpp/acl_cpp_define.hpp"
#include "acl_cpp/stdlib/string.hpp"
#include <map>
struct ACL_VSTREAM;
@ -63,14 +65,25 @@ public:
/**
*
* @param ctx {void*}
* @param key {const char* } ctx
*/
void set_ctx(void* ctx);
void set_ctx(void* ctx, const char* key = NULL);
/**
*
* @param key {const char* key} 使 key ctx
* ctx
* @return {void*}
*/
void* get_ctx() const;
void* get_ctx(const char* key = NULL) const;
/**
*
* @param key {const char*} key ctx
* ctx
* @return {void*} NULL
*/
void* del_ctx(const char* key = NULL);
/**
*
@ -89,7 +102,8 @@ protected:
bool eof_;
bool opened_;
void* ctx_;
void* default_ctx_;
std::map<string, void*> ctx_table_;
};
} // namespace acl

View File

@ -52,6 +52,7 @@ all:
@(cd http_request_manager; make)
@(cd dircopy; make)
@(cd scan_dir; make)
@(cd socket; make)
clean:
@(cd string; make clean)
@ -107,3 +108,4 @@ clean:
@(cd http_request_manager; make clean)
@(cd dircopy; make clean)
@(cd scan_dir; make clean)
@(cd socket; make clean)

View File

@ -71,10 +71,18 @@ ifneq ($(SYSPATH),)
endif
###########################################################
CFLAGS += -I. -I../../include -I../../../lib_acl/include -I../../../lib_protocol/include
BASE_PATH =
ifneq ($(base_path),)
BASE_PATH = $(base_path)
else
BASE_PATH = ../..
endif
CFLAGS += -I. -I$(BASE_PATH)/include -I$(BASE_PATH)/../lib_acl/include -I$(BASE_PATH)/../lib_protocol/include
EXTLIBS =
LDFLAGS = -L../../lib -l_acl_cpp -L../../../lib_protocol/lib -l_protocol -L../../../lib_acl/lib -l_acl \
-L../../../lib/$(RPATH) $(EXTLIBS) $(SYSLIB)
LDFLAGS = -L$(BASE_PATH)/lib -l_acl_cpp -L$(BASE_PATH)/../lib_protocol/lib -l_protocol -L$(BASE_PATH)/../lib_acl/lib -l_acl \
-L$(BASE_PATH)/../lib/$(RPATH) $(EXTLIBS) $(SYSLIB)
COMPILE = $(CC) $(CFLAGS)
LINK = $(CC) $(OBJ) $(LDFLAGS)

View File

@ -1,2 +1,3 @@
include ../Makefile.in
base_path = ../../..
include ../../Makefile.in
PROG = aio_client

View File

@ -1,2 +1,3 @@
include ../Makefile.in
base_path = ../../..
include ../../Makefile.in
PROG = aio_dns

View File

@ -1,2 +1,3 @@
include ../Makefile.in
base_path = ../../..
include ../../Makefile.in
PROG = aio_echo

View File

@ -1,2 +1,3 @@
include ../Makefile.in
base_path = ../../..
include ../../Makefile.in
PROG = aio_ipc

View File

@ -1,2 +1,3 @@
include ../Makefile.in
base_path = ../../..
include ../../Makefile.in
PROG = aio_server

View File

@ -179,7 +179,8 @@ public:
// 读取 HTTP 客户端请求数据
while (len > 0)
{
k = len > sizeof(buf) ? sizeof(buf) : len;
k = len > (long long int) sizeof(buf)
? (long long int) sizeof(buf) : len;
ret = in.read(buf, k, false);
if (ret == -1)
{

View File

@ -0,0 +1,9 @@
.PHONY = all clean
all:
@(cd client; make)
@(cd server; make)
clean:
@(cd client; make clean)
@(cd server; make clean)

View File

@ -0,0 +1,3 @@
base_path = ../../..
include ../../Makefile.in
PROG = socket_client

View File

@ -0,0 +1,85 @@
#include "acl_cpp/lib_acl.hpp"
#include "lib_acl.h"
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
acl::socket_stream client;
acl::string addr = "127.0.0.1:9001";
if (client.open(addr, 0, 0) == false)
{
printf("open %s error\n", addr.c_str());
return 1;
}
else
printf("open %s ok\r\n", addr.c_str());
// 探测连接是否正常
if (client.alive())
printf("first check: ok, status: %s\r\n", acl::last_serror());
else
printf("first check: disconnected, status: %s\r\n",
acl::last_serror());
// 读服务器端写入的一行数据
acl::string buf;
if (client.gets(buf) == false)
{
printf("gets error, status: %s\r\n", acl::last_serror());
return 1;
}
printf("gets: %s\r\n", buf.c_str());
// 探测连接是否正常
if (client.alive())
printf("second check: ok, status: %s\r\n", acl::last_serror());
else
printf("second check: disconnected, status: %s\r\n",
acl::last_serror());
acl::string req = "echo1\r\n"
"echo2\r\n"
"echo3\r\n"
"read_delay1\r\n"
"read_delay2\r\n"
"read_delay3\r\n"
"read_delay4\r\n"
"read_delay5\r\n"
"quit\r\n";
int n = 10;
printf("sleep %d second\r\n", n);
// 休息一下,以保证服务器肯定已经关闭了连接
for (int i = 0; i < n; i++)
{
sleep(1);
putchar('.');
fflush(stdout);
}
printf("\r\n");
// 检查第一次写入时 write 是否返回失败
if ((n = client.write(req.c_str(), req.length())) < 0)
{
printf("first write error, status: %s\n", acl::last_serror());
return 1;
}
else
printf("first write ok, ret: %d, status: %s\r\n",
n, acl::last_serror());
// 检查第二次写入时 write 是否返回失败
if ((n = client.write(req.c_str(), req.length())) < 0)
{
printf("second write error, status: %s\n", acl::last_serror());
return 1;
}
else
printf("second write ok: ret: %d, status: %s\r\n",
n, acl::last_serror());
return (0);
}

View File

@ -0,0 +1,3 @@
base_path = ../../..
include ../../Makefile.in
PROG = socket_server

View File

@ -0,0 +1,39 @@
#include "acl_cpp/lib_acl.hpp"
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
acl::server_socket server;
acl::string addr = "127.0.0.1:9001";
if (server.open(addr) == false)
{
printf("open %s error\r\n", addr.c_str());
return 1;
}
else
printf("open %s ok\r\n", addr.c_str());
while (true)
{
acl::socket_stream* client = server.accept();
if (client == NULL)
{
printf("accept failed: %s\r\n", acl::last_serror());
break;
}
if (client->write("hello world\r\n") == false)
{
printf("write error\r\n");
delete client;
continue;
}
delete client;
printf("close client ok\r\n");
}
return (0);
}

View File

@ -27,7 +27,7 @@ int main(void)
"read_delay5\r\n"
"quit\r\n";
if (client.write(req.c_str(), req.length()) == false)
if (client.write(req.c_str(), req.length()) == -1)
{
printf("write error\n");
getchar();

View File

@ -184,16 +184,17 @@ bool http_request::write_head()
need_retry_ = false;
// 如果请求方法非 GET则需要首先探测一下连接是否正常
if (method != HTTP_METHOD_GET)
if (method != HTTP_METHOD_GET && method != HTTP_METHOD_PURGE)
{
socket_stream& ss = client_->get_stream();
ACL_VSTREAM* vs = ss.get_vstream();
// 因为系统 write API 成功并不能保证连接正常,所以只能是调用
// 系统 read API 来探测连接是否正常,该函数内部会将套接口先转
// 非阻塞套接口进行读操作,所以不会阻塞,同时即使有数据读到也会
// 先放到 ACL_VSTREAM 的读缓冲中,所以也不会丢失数据
if (acl_vstream_probe_status(vs) == -1)
/* 因为系统 write API 成功并不能保证连接正常,所以只能
* read API
*
* 使 ACL_VSTREAM
*
*/
if (ss.alive() == false)
{
close();

View File

@ -254,6 +254,16 @@ const char* socket_stream::get_ip(const char* addr, char* buf, size_t size)
return buf;
}
bool socket_stream::alive(void) const
{
if (stream_ == NULL)
return false;
if (acl_vstream_probe_status(stream_) == -1)
return false;
else
return true;
}
bool socket_stream::open_ssl_client(void)
{
if (stream_ == NULL)

View File

@ -1,4 +1,5 @@
#include "acl_stdafx.hpp"
#include "acl_cpp/stdlib/string.hpp"
#include "acl_cpp/stream/stream.hpp"
namespace acl {
@ -7,7 +8,7 @@ stream::stream(void)
: stream_(NULL)
, eof_(true)
, opened_(false)
, ctx_(NULL)
, default_ctx_(NULL)
{
}
@ -74,14 +75,42 @@ void stream::reopen_stream(void)
open_stream();
}
void stream::set_ctx(void* ctx)
void stream::set_ctx(void* ctx, const char* key /* = NULL */)
{
ctx_ = ctx;
if (key == NULL || *key == 0)
default_ctx_ = ctx;
else
ctx_table_[key] = ctx;
}
void* stream::get_ctx() const
void* stream::get_ctx(const char* key /* = NULL */) const
{
return ctx_;
if (key == NULL || *key == 0)
return default_ctx_;
std::map<string, void*>::const_iterator it = ctx_table_.find(key);
if (it != ctx_table_.end())
return it->second;
else
return NULL;
}
void* stream::del_ctx(const char* key /* = NULL */)
{
if (key == NULL || *key == 0)
{
if (default_ctx_ == NULL)
return false;
void* ctx = default_ctx_;
default_ctx_ = NULL;
return ctx;
}
std::map<string, void*>::iterator it = ctx_table_.find(key);
if (it == ctx_table_.end())
return NULL;
void *ctx = it->second;
ctx_table_.erase(it);
return ctx;
}
} // namespace acl