mirror of
https://gitee.com/acl-dev/acl.git
synced 2024-11-30 02:47:56 +08:00
完善接口功能,添加网络示例
This commit is contained in:
parent
79e18cc2e9
commit
54aa697c22
@ -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 方法,
|
||||
则增加了有效的重试机制
|
||||
|
@ -134,6 +134,13 @@ public:
|
||||
*/
|
||||
bool set_local(const char* addr);
|
||||
|
||||
/**
|
||||
* 检查套接口连接的存活状态(内部使用了非阻塞读的方式进行探测)
|
||||
* @return {bool} 当网络连接未打开或已经关闭时该函数返回 false,如果
|
||||
* 连接正常则返回 true
|
||||
*/
|
||||
bool alive() const;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
void close_ssl(void);
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -1,2 +1,3 @@
|
||||
include ../Makefile.in
|
||||
base_path = ../../..
|
||||
include ../../Makefile.in
|
||||
PROG = aio_client
|
||||
|
@ -1,2 +1,3 @@
|
||||
include ../Makefile.in
|
||||
base_path = ../../..
|
||||
include ../../Makefile.in
|
||||
PROG = aio_dns
|
||||
|
@ -1,2 +1,3 @@
|
||||
include ../Makefile.in
|
||||
base_path = ../../..
|
||||
include ../../Makefile.in
|
||||
PROG = aio_echo
|
||||
|
@ -1,2 +1,3 @@
|
||||
include ../Makefile.in
|
||||
base_path = ../../..
|
||||
include ../../Makefile.in
|
||||
PROG = aio_ipc
|
||||
|
@ -1,2 +1,3 @@
|
||||
include ../Makefile.in
|
||||
base_path = ../../..
|
||||
include ../../Makefile.in
|
||||
PROG = aio_server
|
||||
|
@ -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)
|
||||
{
|
||||
|
9
lib_acl_cpp/samples/socket/Makefile
Normal file
9
lib_acl_cpp/samples/socket/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
.PHONY = all clean
|
||||
|
||||
all:
|
||||
@(cd client; make)
|
||||
@(cd server; make)
|
||||
|
||||
clean:
|
||||
@(cd client; make clean)
|
||||
@(cd server; make clean)
|
3
lib_acl_cpp/samples/socket/client/Makefile
Normal file
3
lib_acl_cpp/samples/socket/client/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
base_path = ../../..
|
||||
include ../../Makefile.in
|
||||
PROG = socket_client
|
85
lib_acl_cpp/samples/socket/client/main.cpp
Normal file
85
lib_acl_cpp/samples/socket/client/main.cpp
Normal 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);
|
||||
}
|
3
lib_acl_cpp/samples/socket/server/Makefile
Normal file
3
lib_acl_cpp/samples/socket/server/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
base_path = ../../..
|
||||
include ../../Makefile.in
|
||||
PROG = socket_server
|
39
lib_acl_cpp/samples/socket/server/main.cpp
Normal file
39
lib_acl_cpp/samples/socket/server/main.cpp
Normal 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);
|
||||
}
|
@ -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();
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user