利用ACL開發併發網絡服務器

一、概述
    本節結合 "利用ACL庫開發高併發半駐留式線程池程序" 和 "利用ACL庫快速建立你的網絡程序" 兩篇文章的內容,建立一個簡單的線程池網絡服務器程序。
二、併發式網絡通訊實例html

#include "lib_acl.h"  /* 先包含ACL庫頭文件 */
#include <stdio.h>
#include <stdlib.h>

/**
 * 單獨的線程處理來自於客戶端的鏈接
 * @param arg {void*} 添加任務時的對象
 */
static void echo_client_thread(void *arg)
{
	ACL_VSTREAM *client = (ACL_VSTREAM*) arg;
	char  buf[1024];
	int   n;

	/* 設置客戶端流的讀超時時間爲30秒 */
	ACL_VSTREAM_SET_RWTIMO(client, 30);

	/* 循環讀客戶端的數據,直到其關閉或出錯或超時 */
	while (1) {
		/* 等待讀客戶端發來的數據 */
		n = acl_vstream_read(client, buf, sizeof(buf));
		if (n == ACL_VSTREAM_EOF)
			break;
		/* 將讀到的數據寫回至客戶端流 */
		if (acl_vstream_writen(client, buf, n) == ACL_VSTREAM_EOF)
			break;
	}

	/* 關閉客戶端流 */
	acl_vstream_close(client);
}

/**
 * 建立半駐留線程池的過程
 * @return {acl_pthread_pool_t*} 新建立的線程池句柄
 */
static acl_pthread_pool_t *create_thread_pool(void)
{
	acl_pthread_pool_t *thr_pool;  /* 線程池句柄 */
	int  max_threads = 100;  /* 最多併發100個線程 */
	int  idle_timeout = 10;  /* 每一個工做線程空閒10秒後自動退出 */
	acl_pthread_pool_attr_t attr;  /* 線程池初始化時的屬性 */

	/* 初始化線程池對象屬性 */
	acl_pthread_pool_attr_init(&attr);
	acl_pthread_pool_attr_set_threads_limit(&attr, max_threads);
	acl_pthread_pool_attr_set_idle_timeout(&attr, idle_timeout);

	/* 建立半駐留線程句柄 */
	thr_pool = acl_pthread_pool_create(&attr);
	assert(thr_pool);
	return (thr_pool);
}

/**
 * 開始運行
 * @param addr {const char*} 服務器監聽地址,如:127.0.0.1:8081
 */
static void run(const char *addr)
{
	const char *myname = "run";
	acl_pthread_pool_t *thr_pool;
	ACL_VSTREAM *sstream;
	char  ebuf[256];

	thr_pool = create_thread_pool();

	/* 監聽一個本地地址 */
	sstream = acl_vstream_listen(addr, 128);
	if (sstream == NULL) {
		printf("%s(%d): listen on %s error(%s)\r\n",
				myname, __LINE__, addr,
				acl_last_strerror(ebuf, sizeof(ebuf)));
		return;
	}

	printf("%s: listen %s ok\r\n", myname, addr);
	while (1) {
		/* 等待接受客戶端的鏈接 */
		client = acl_vstream_accept(sstream, NULL, 0);
		if (client == NULL) {
			printf("%s(%d): accept error(%s)\r\n",
					myname, __LINE__,
					acl_last_strerror(ebuf, sizeof(ebuf)));
			break;
		}
		printf("accept one\r\n");
		/* 得到一個客戶端鏈接流 */
		/* 開始處理該客戶端鏈接流 */

		/**
		 * 向線程池中添加一個任務
		 * @param thr_pool 線程池句柄
		 * @param echo_client_thread 工做線程的回調函數
		 * @param client 客戶端數據流
		 */
		acl_pthread_pool_add(thr_pool, echo_client_thread, client);
	}

	/* 銷燬線程池對象 */
	acl_pthread_pool_destroy(thr_pool);
}

/**
 * 初始化過程
 */
static void init(void)
{
	/* 初始化ACL庫 */
	acl_init();
}

/**
 * 使用提示接口
 * @param procname {cosnt char*} 程序名
 */
static void usage(const char *procname)
{
	printf("usage: %s listen_addr\r\n", procname);
	printf("example: %s 127.0.0.1:8081\r\n", procname);
	getchr();  
}

int main(int argc, char *argv[])
{
	if (argc != 2) {
		usage(argv[0]);
		return (0);
	}

	init();
	run(argv[1]);
	return (0);
}

 


    由上能夠看出,建立一個併發式服務器程序也是如此的簡單。 該例子能夠同時運行在WIN32平臺及UNIX平臺(Linux, FreeBSD, Solaris-x86).

三、小結
    由以上例子能夠看出,ACL庫屏蔽底層SOCKET的細節操做,使網絡編程變得簡單,使使用者能夠專心於其應用,而不是拘泥於SOCKET操做上,另外結合半駐留線程池的ACL庫就能夠開發高效的併發網絡應用來。
  固然,以上例子也存在一個缺點,那就是當客戶端併發鏈接比較高時,由於一個鏈接佔用一個線程,因此高併發時就須要更多的線程(爲了啓動更多的線程,能夠經過 acl_pthread_pool_set_stacksize 或 acl_pthread_pool_attr_set_stacksize 設置每一個線程的堆棧爲較小的值,如 500KB);而採用ACL庫裏的另外一種編程技術--非阻塞式IO,可使一個線程同時處理多個併發TCP鏈接,同時能夠啓動多個這樣的非阻塞線程,從而能夠更好地利用多核(通常是一個核能夠啓用一個非阻塞IO線程),未來,咱們將會對此類問題進行討論,並給出具體實例。

   acl 庫的下載地址:http://acl.sourceforge.net/
   acl 庫的在線幫助地址:http://acl.sourceforge.net/acl_help/index.htmlgit

 

4 參考github

1)  利用ACL庫快速建立你的網絡程序--ACL_VSTREAM 流的使用編程

2)  利用ACL庫開發高併發半駐留式線程池程序服務器

 

下載:http://sourceforge.net/projects/acl/網絡

svn:svn checkout svn://svn.code.sf.net/p/acl/code/trunk acl-code併發

github:https://github.com/zhengshuxin/aclsvn

QQ 羣:242722074函數

相關文章
相關標籤/搜索