add acl_read_xxx_wait with milliseconds;

icmp ping supports timeout and delay with milliseconds;
This commit is contained in:
zhengshuxin 2017-08-15 12:17:57 +08:00
parent 267bd5db63
commit be7629ced2
12 changed files with 136 additions and 69 deletions

View File

@ -1,6 +1,9 @@
修改历史列表:
------------------------------------------------------------------------
604) 2017.8.15
604.1) feature: 开放 acl_read_xxx_wait 接口,以允许毫秒级读超时等待
603) 2017.8.11
603.1) stable: acl_chroot_uid 内部如果出错则不会自动崩溃,给是返回 -1 通知上层

View File

@ -52,6 +52,34 @@ ACL_API int acl_write_wait(ACL_SOCKET fd, int timeout);
*/
ACL_API int acl_read_wait(ACL_SOCKET fd, int timeout);
#if defined(ACL_LINUX) && !defined(MINGW)
/**
* epoll
* @param fd {ACL_SOCKET}
* @param delay {int}
* @return {int}
*/
ACL_API int acl_read_epoll_wait(ACL_SOCKET fd, int delay);
#endif
#if defined(ACL_UNIX)
/**
* poll
* @param fd {ACL_SOCKET}
* @param delay {int}
* @return {int}
*/
ACL_API int acl_read_poll_wait(ACL_SOCKET fd, int delay);
#endif
/**
* select
* @param fd {ACL_SOCKET}
* @param delay {int}
* @return {int}
*/
ACL_API int acl_read_select_wait(ACL_SOCKET fd, int delay);
/**
* ºÁÃë¼±ð˯Ãß
* @param delay {unsigned} ºÁÃëÖµ

View File

@ -22,7 +22,7 @@
#include "stdlib/acl_iostuff.h"
#include "../../init/init.h"
#if defined(ACL_LINUX) && !defined(MINGW) && defined(USE_EPOLL)
#if defined(ACL_LINUX) && !defined(MINGW)
#include "init/acl_init.h"
#include "thread/acl_pthread.h"
@ -116,10 +116,10 @@ static int thread_epoll_reopen(EPOLL_CTX *epoll_ctx)
return 0;
}
int acl_read_wait(ACL_SOCKET fd, int timeout)
int acl_read_epoll_wait(ACL_SOCKET fd, int delay)
{
const char *myname = "acl_read_wait";
int delay = timeout * 1000, ret, retried = 0;
const char *myname = "acl_read_epoll_wait";
int ret, retried = 0;
EPOLL_CTX *epoll_ctx;
struct epoll_event ee, events[1];
time_t begin;
@ -243,13 +243,14 @@ int acl_read_wait(ACL_SOCKET fd, int timeout)
return ret;
}
#elif defined(ACL_UNIX)
#endif
int acl_read_wait(ACL_SOCKET fd, int timeout)
#if defined(ACL_UNIX)
int acl_read_poll_wait(ACL_SOCKET fd, int delay)
{
const char *myname = "acl_read_wait";
const char *myname = "acl_read_poll_wait";
struct pollfd fds;
int delay = timeout * 1000;
time_t begin;
fds.events = POLLIN | POLLHUP | POLLERR;
@ -300,19 +301,21 @@ int acl_read_wait(ACL_SOCKET fd, int timeout)
}
}
#elif defined(WIN32_XX)
#endif
#if defined(WIN32_XX)
static HANDLE __handle = NULL;
int acl_read_wait(ACL_SOCKET fd, int timeout)
int acl_read_iocp_wait(ACL_SOCKET fd, int timeout)
{
const char *myname = "acl_read_wait";
const char *myname = "acl_read_iocp_wait";
OVERLAPPED *overlapped, *lpOverlapped;
DWORD recvBytes;
BOOL isSuccess;
ACL_SOCKET fd2;
DWORD bytesTransferred = 0;
DWORD delay = timeout * 1000;
DWORD delay = timeout;
HANDLE h2;
if (__handle == NULL)
@ -368,11 +371,11 @@ int acl_read_wait(ACL_SOCKET fd, int timeout)
return -1;
}
#else
#endif
int acl_read_wait(ACL_SOCKET fd, int timeout)
int acl_read_select_wait(ACL_SOCKET fd, int delay)
{
const char *myname = "acl_read_wait";
const char *myname = "acl_read_select_wait";
fd_set rfds, xfds;
struct timeval tv;
struct timeval *tp;
@ -400,9 +403,9 @@ int acl_read_wait(ACL_SOCKET fd, int timeout)
FD_ZERO(&xfds);
FD_SET(fd, &xfds);
if (timeout >= 0) {
if (delay >= 0) {
tv.tv_usec = 0;
tv.tv_sec = timeout;
tv.tv_sec = delay / 1000;
tp = &tv;
} else
tp = 0;
@ -449,4 +452,13 @@ int acl_read_wait(ACL_SOCKET fd, int timeout)
}
}
int acl_read_wait(ACL_SOCKET fd, int timeout)
{
#if defined(ACL_LINUX) && !defined(MINGW) && defined(USE_EPOLL)
return acl_read_epoll_wait(fd, timeout * 1000);
#elif defined(ACL_UNIX)
return acl_read_poll_wait(fd, timeout * 1000);
#else
return acl_read_select_wait(fd, timeout * 1000);
#endif
}

View File

@ -430,7 +430,7 @@ int event_process(EVENT *ev, int timeout)
* quickly when no tasks left
*/
if (timeout > 1000 || timeout <= 0)
timeout = 1000;
timeout = 100;
#ifdef DEL_DELAY
ndefer = ev->r_ndefer;

View File

@ -5,7 +5,8 @@
static int __nfibers = 0;
static int __npkt = 10;
static int __delay_seconds = 1; /* 发送 ping 包的时间间隔(秒)*/
static int __delay = 10;
static int __timeout = 1000;
static int __benchmark = 0;
static void display_res(ICMP_CHAT *chat)
@ -45,9 +46,9 @@ static void fiber_ping(ACL_FIBER *fiber acl_unused, void *arg)
/* 开始 PING */
if (strcmp(dest, ip) == 0)
icmp_ping_one(chat, NULL, ip, __npkt, __delay_seconds, 1);
icmp_ping_one(chat, NULL, ip, __npkt, __delay, __timeout);
else
icmp_ping_one(chat, dest, ip, __npkt, __delay_seconds, 1);
icmp_ping_one(chat, dest, ip, __npkt, __delay, __timeout);
acl_netdb_free(dns_db); /* 释放域名解析对象 */
display_res(chat); /* 显示 PING 结果 */
@ -60,7 +61,8 @@ static void fiber_ping(ACL_FIBER *fiber acl_unused, void *arg)
static void usage(const char* progname)
{
printf("usage: %s -h help\r\n"
" -d delay\r\n"
" -d delay[milliseconds]\r\n"
" -t timout[milliseconds]\r\n"
" -z stack_size\r\n"
" -b benchmark [if > 0 dest will be ignored]\r\n"
" -n npkt dest1 dest2...\r\n", progname);
@ -82,7 +84,7 @@ int main(int argc, char* argv[])
signal(SIGINT, on_sigint); /* 用户按下 ctr + c 时中断 PING 程序 */
acl_msg_stdout_enable(1); /* 允许 acl_msg_xxx 记录的信息输出至屏幕 */
while ((ch = getopt(argc, argv, "hn:d:z:b:")) > 0) {
while ((ch = getopt(argc, argv, "hn:d:z:b:t:")) > 0) {
switch (ch) {
case 'n':
__npkt = atoi(optarg);
@ -94,7 +96,10 @@ int main(int argc, char* argv[])
stack_size = atoi(optarg);
break;
case 'd':
__delay_seconds = atoi(optarg);
__delay = atoi(optarg);
break;
case 't':
__timeout = atoi(optarg);
break;
case 'b':
__benchmark = atoi(optarg);

View File

@ -5,6 +5,7 @@
在异步 IO 模式与 event 事件引擎设置的该标志位,否则会造成 IO 死循环
261.2) feature: icmp_chat.c 中将 ICMP_CHAT::tid 由原来的线程 ID 改为原子加值,
以支持协程模式下使用
261.3) feature: 将 ICMP_HOST::delay 的单位由秒调整为毫秒
260) 2016.5.10
260.1) feature: http_hdr_res.c 中的函数 http_hdr_res_parse 取消了对 http_status

View File

@ -96,8 +96,8 @@ ICMP_API void icmp_stat_host(ICMP_HOST *host, int show_flag);
* @param ip {const char*} IP地址
* @param npkt {size_t}
* @param dlen {size_t}
* @param delay {int} ()
* @param timeout {int} ()
* @param delay {int} ()
* @param timeout {int} ()
* @return {ICMP_HOST*} ,
*/
ICMP_API ICMP_HOST* icmp_host_new(ICMP_CHAT *chat, const char *domain,
@ -131,8 +131,8 @@ ICMP_API void icmp_host_set(ICMP_HOST *host, void *arg,
* @param domain {const char*}
* @param ip {const char*} IP地址
* @param npkt {size_t}
* @param delay {int} ()
* @param timeout {int} ()
* @param delay {int} ()
* @param timeout {int} ()
*/
ICMP_API void icmp_ping_one(ICMP_CHAT *chat, const char *domain,
const char *ip, size_t npkt, int delay, int timeout);

View File

@ -15,7 +15,7 @@ struct ICMP_STAT {
double tave; /**< 平均时间 */
size_t nsent; /**< 已经发送的包个数 */
size_t nreceived; /**< 已经收到的包个数 */
double loss; /**< 丢失的包个数 */
double loss; /**< 丢失的包个数 */
};
/**< ICMP 所发送的每个 PING 包之后的主机状态应答 */
@ -40,8 +40,8 @@ struct ICMP_HOST {
struct sockaddr_in dest; /**< 发送包时目的主机地址 */
struct sockaddr_in from; /**< 接收包时源主机地址 */
int from_len; /**< 接收包时存储在 from 中的地址长度 */
int delay; /**< 间隔发送PING包的时间单位为秒 */
int timeout; /**< 超时时间 */
int delay; /**< 间隔发送PING包的时间单位为秒 */
int timeout; /**< 超时时间(毫秒) */
size_t dlen; /**< 每个发送包的大小(字节) */
size_t npkt; /**< 设置的向该目的主机发送包的个数 */
size_t nsent; /**< 已经发送给该目的主机包的个数 */

View File

@ -3,8 +3,9 @@
#include "lib_acl.h"
#include <signal.h>
static void add_ip_list(ICMP_CHAT *chat, const ACL_ARGV *domain_list,
int npkt, int delay)
static int __delay = 1;
static void add_ip_list(ICMP_CHAT *chat, const ACL_ARGV *domain_list, int npkt)
{
ACL_DNS_DB* dns_db;
const char* ptr;
@ -33,9 +34,9 @@ static void add_ip_list(ICMP_CHAT *chat, const ACL_ARGV *domain_list,
pip = ip_list->argv[i++];
if (strcmp(pdomain, pip) == 0)
icmp_ping_one(chat, NULL, pip, npkt, delay, 1);
icmp_ping_one(chat, NULL, pip, npkt, __delay, 1);
else
icmp_ping_one(chat, pdomain, pip, npkt, delay, 1);
icmp_ping_one(chat, pdomain, pip, npkt, __delay, 1);
}
}
@ -64,7 +65,6 @@ static void display_res(void)
/* 单线程异步 PING 多个地址的函数入口 */
static void ping_main_async(const ACL_ARGV *ip_list, int npkt)
{
int delay = 1;
ACL_AIO *aio;
/* 创建非阻塞异步通信句柄 */
@ -75,7 +75,7 @@ static void ping_main_async(const ACL_ARGV *ip_list, int npkt)
__chat = icmp_chat_create(aio, 1);
/* 添加需要 PING 的地址列表 */
add_ip_list(__chat, ip_list, npkt, delay);
add_ip_list(__chat, ip_list, npkt);
while (1) {
/* 如果 PING 结束,则退出循环 */
@ -100,7 +100,6 @@ static void ping_main_async(const ACL_ARGV *ip_list, int npkt)
static void ping_main_sync(const char *dest, int npkt)
{
ACL_DNS_DB* dns_db;
int delay = 1;
const char* ip;
/* 创建 ICMP 对象 */
@ -119,9 +118,9 @@ static void ping_main_sync(const char *dest, int npkt)
/* 开始 PING 一个 IP 地址 */
if (strcmp(dest, ip) == 0)
icmp_ping_one(__chat, NULL, ip, npkt, delay, 1);
icmp_ping_one(__chat, NULL, ip, npkt, __delay, 1);
else
icmp_ping_one(__chat, dest, ip, npkt, delay, 1);
icmp_ping_one(__chat, dest, ip, npkt, __delay, 1);
/* 释放 DNS 查询结果 */
acl_netdb_free(dns_db);
@ -136,7 +135,6 @@ static void *ping_thread(void *arg)
{
const char *ip, *dest = (char *) arg;
ACL_DNS_DB* dns_db;
int delay = 1;
ICMP_CHAT *chat;
/* 通过域名解析出IP地址 */
@ -159,9 +157,9 @@ static void *ping_thread(void *arg)
/* 开始 PING */
if (strcmp(dest, ip) == 0)
icmp_ping_one(chat, NULL, ip, __npkt, delay, 1);
icmp_ping_one(chat, NULL, ip, __npkt, __delay, 1);
else
icmp_ping_one(chat, dest, ip, __npkt, delay, 1);
icmp_ping_one(chat, dest, ip, __npkt, __delay, 1);
acl_netdb_free(dns_db); /* 释放域名解析对象 */
display_res2(chat); /* 显示 PING 结果 */
icmp_chat_free(chat); /* 释放 ICMP 对象 */
@ -192,7 +190,7 @@ static void ping_main_threads(const ACL_ARGV *ip_list, int npkt)
static void usage(const char* progname)
{
printf("usage: %s [-h help] -s [sync] -t [use thread mode] [-n npkt] [\"dest1 dest2 dest3...\"]\r\n", progname);
printf("usage: %s [-h help] -s [sync] -d delay -t [use thread mode] [-n npkt] [\"dest1 dest2 dest3...\"]\r\n", progname);
printf("example: %s -n 10 www.sina.com.cn www.baidu.com www.qq.com\r\n", progname);
printf("example: %s -s -n 10 www.sina.com.cn\r\n", progname);
#ifdef WIN32
@ -218,7 +216,7 @@ int main(int argc, char* argv[])
acl_socket_init(); /* 在 WIN32 下需要初始化全局套接字库 */
acl_msg_stdout_enable(1); /* 允许 acl_msg_xxx 记录的信息输出至屏幕 */
while ((ch = getopt(argc, argv, "htsl:n:")) > 0) {
while ((ch = getopt(argc, argv, "htsl:n:d:")) > 0) {
switch (ch) {
case 'h':
usage(argv[0]);
@ -232,6 +230,9 @@ int main(int argc, char* argv[])
case 'n':
npkt = atoi(optarg);
break;
case 'd':
__delay = atoi(optarg);
break;
default:
usage(argv[0]);
return (0);

View File

@ -21,25 +21,30 @@ static void check_timer(int event_type acl_unused,
pkt = (ICMP_PKT*) chat->timer->popup(chat->timer);
if (pkt == NULL)
break;
/* 汇报请求包超时 */
icmp_stat_timeout(pkt);
/* 获得发往该主机的下一个数据包 */
pkt_next = ICMP_PKT_NEXT(&pkt->icmp_host->pkt_head, &pkt->pkt_ring);
pkt_next = ICMP_PKT_NEXT(
&pkt->icmp_host->pkt_head, &pkt->pkt_ring);
/* 定时发送下一个请求数据包 */
if (pkt_next != NULL)
delay_send_pkt(pkt_next, 0);
else {
/* 如果对该主机的包发送完毕,则回调状态汇报函数 */
if (pkt->icmp_host->stat_finish)
pkt->icmp_host->stat_finish(pkt->icmp_host, pkt->icmp_host->arg);
pkt->icmp_host->stat_finish(
pkt->icmp_host, pkt->icmp_host->arg);
/* 已完成主机检测数加1 */
chat->count++;
}
}
/* 启动下一次定时器 */
acl_aio_request_timer(chat->aio, check_timer, chat, chat->check_inter, 0);
acl_aio_request_timer(chat->aio, check_timer,
chat, chat->check_inter, 0);
}
static void send_pkt(ICMP_PKT *pkt)
@ -52,10 +57,11 @@ static void send_pkt(ICMP_PKT *pkt)
/* 组建发送数据包 */
icmp_pkt_build(pkt, chat->seq_no++);
/* 指定当前包目的主机地址,间接传递给 acl_vstream_writen 的回调函数 */
/* 指定当前包目的主机地址,间接传递给 acl_vstream_writen 的回调函数 */
chat->is->curr_host = pkt->icmp_host;
/* 采用同步发送的模式 */
ret = acl_vstream_writen(vstream, (const char*) pkt, (int) pkt->write_len);
ret = acl_vstream_writen(vstream, (const char*) pkt,
(int) pkt->write_len);
pkt->icmp_host->nsent++;
if (ret == ACL_VSTREAM_EOF) {
@ -64,7 +70,8 @@ static void send_pkt(ICMP_PKT *pkt)
/* 汇报主机不可达信息 */
icmp_stat_unreach(pkt);
pkt_next = ICMP_PKT_NEXT(&pkt->icmp_host->pkt_head, &pkt->pkt_ring);
pkt_next = ICMP_PKT_NEXT(&pkt->icmp_host->pkt_head,
&pkt->pkt_ring);
if (pkt_next != NULL) {
/* 延迟发送下一个数据包 */
delay_send_pkt(pkt_next, pkt_next->icmp_host->delay);
@ -74,7 +81,8 @@ static void send_pkt(ICMP_PKT *pkt)
/* 汇报该 ICMP_HOST 对象的 ICMP 包可达状态 */
if (pkt->icmp_host->stat_finish)
pkt->icmp_host->stat_finish(pkt->icmp_host, pkt->icmp_host->arg);
pkt->icmp_host->stat_finish(
pkt->icmp_host, pkt->icmp_host->arg);
}
} else {
/* 将该包置入超时队列中 */
@ -112,10 +120,11 @@ static void delay_send_pkt(ICMP_PKT *pkt, int delay)
if (pkt == NULL)
acl_msg_fatal("%s(%d): pkt null", myname, __LINE__);
/* 启动写定时器,因为传入的 delay 是秒级,而 acl_aio_request_timer
* , dely
/* 启动写定时器,因为传入的 delay 是秒级,而 acl_aio_request_timer
* , dely
*/
acl_aio_request_timer(pkt->pkt_chat->aio, delay_send_timer, pkt, delay * 1000000, 0);
acl_aio_request_timer(pkt->pkt_chat->aio, delay_send_timer,
pkt, delay * 1000, 0);
}
static int read_close_fn(ACL_ASTREAM *astream acl_unused, void *arg)
@ -137,7 +146,8 @@ static int read_close_fn(ACL_ASTREAM *astream acl_unused, void *arg)
return (-1);
}
static int read_ready_fn(ACL_ASTREAM *astream, void *arg, const char *data, int dlen)
static int read_ready_fn(ACL_ASTREAM *astream, void *arg,
const char *data, int dlen)
{
const char *myname = "read_ready_fn";
ICMP_CHAT *chat = (ICMP_CHAT*) arg;
@ -169,10 +179,12 @@ static int read_ready_fn(ACL_ASTREAM *astream, void *arg, const char *data, int
/* 汇报状态 */
icmp_stat_report(pkt_src);
pkt_next = ICMP_PKT_NEXT(&pkt_src->icmp_host->pkt_head, &pkt_src->pkt_ring);
pkt_next = ICMP_PKT_NEXT(&pkt_src->icmp_host->pkt_head,
&pkt_src->pkt_ring);
if (pkt_next == NULL) {
if (pkt_src->icmp_host->stat_finish)
pkt_src->icmp_host->stat_finish(pkt_src->icmp_host, pkt_src->icmp_host->arg);
pkt_src->icmp_host->stat_finish(
pkt_src->icmp_host, pkt_src->icmp_host->arg);
chat->count++;
READ_RETURN(0);
}

View File

@ -9,7 +9,14 @@ static void read_pkt(ACL_VSTREAM *stream, ICMP_PKT *pkt_src)
int ret;
while (1) {
if (acl_read_wait(ACL_VSTREAM_SOCK(stream), pkt_src->icmp_host->timeout) < 0) {
#ifdef ACL_UNIX
if (acl_read_poll_wait(ACL_VSTREAM_SOCK(stream),
pkt_src->icmp_host->timeout) < 0) {
#else
if (acl_read_select_wait(ACL_VSTREAM_SOCK(stream),
pkt_src->icmp_host->timeout) < 0) {
#endif
/* 汇报请求包超时 */
icmp_stat_timeout(pkt_src);
return;
@ -17,8 +24,7 @@ static void read_pkt(ACL_VSTREAM *stream, ICMP_PKT *pkt_src)
ret = acl_vstream_read(stream, buf, sizeof(buf));
if (ret == ACL_VSTREAM_EOF) {
char tbuf[256];
acl_msg_error("read error(%s)", acl_last_strerror(tbuf, sizeof(tbuf)));
acl_msg_error("read error(%s)", acl_last_serror());
continue;
}
@ -62,7 +68,7 @@ void icmp_chat_sio(ICMP_HOST* host)
while (pkt != NULL) {
send_pkt(stream, pkt);
read_pkt(stream, pkt);
sleep(host->delay);
acl_doze(host->delay);
pkt = ICMP_PKT_NEXT(&host->pkt_head, &pkt->pkt_ring);
}

View File

@ -47,12 +47,12 @@ ICMP_HOST* icmp_host_new(ICMP_CHAT *chat, const char *domain, const char *ip,
host->dest.sin_family = AF_INET;
host->dest.sin_addr.s_addr = inet_addr(host->dest_ip);
/* host->dest.sin_port = htons(53); */
host->chat = chat;
host->chat = chat;
host->timeout = timeout;
host->delay = delay;
host->dlen = dlen;
host->npkt = npkt;
host->nsent = 0;
host->delay = delay;
host->dlen = dlen;
host->npkt = npkt;
host->nsent = 0;
acl_ring_init(&host->pkt_head);
for (i = 0; i < npkt; i++) {
@ -74,6 +74,5 @@ void icmp_host_set(ICMP_HOST *host, void *arg,
host->stat_respond = stat_respond;
host->stat_unreach = stat_unreach;
host->stat_timeout = stat_timeout;
host->stat_finish = stat_finish;
host->stat_finish = stat_finish;
}