使用 acl 庫開發簡單的客戶端與服務器程序

      以前寫過一些如何使用 acl 的服務器框架編寫服務器程序的技術文章(http://zsxxsz.iteye.com/category/210570http://zsxxsz.iteye.com/category/80224),若是僅是寫一些簡單的服務器程序,有時倒沒必要如此麻煩, acl 的 C++ 庫部分也提供了一些簡單的服務器類,本文將介紹如何使用這些簡單的類來實現一些服務器程序和網絡客戶端程序。git

      首先介紹 acl 中的服務器類:server_socket。該類定義了以下幾個簡單方法:github

 

/**
	 * 開始監聽給定服務端地址
	 * @param addr {const char*} 服務器監聽地址,格式爲:
	 *  ip:port;在 unix 環境下,還能夠是域套接口,格式爲:
	 *   /path/xxx
	 * @return {bool} 監聽是否成功
	 */
	bool open(const char* addr);

	/**
	 * 關閉已經打開的監聽套接口
	 * @return {bool} 是否正常關閉
	 */
	bool close();

	/**
	 * 接收客戶端鏈接並建立客戶端鏈接流
	 * @param timeout {int} 在阻塞模式下,當該值 > 0 時,採用超時
	 *  方式接收客戶端鏈接,若在指定時間內未得到客戶端鏈接,則返回 NULL
	 * @return {socket_stream*} 返回空表示接收失敗
	 */
	socket_stream* accept(int timeout = 0);

	/**
	 * 得到監聽的地址
	 * @return {const char*} 返回值非空指針
	 */
	const char* get_addr() const
	{
		return addr_;
	}

 

      使用上述網絡服務類的步驟是:調用 open 監聽本機的一個網絡地址(若是是UNIX平臺,還能夠監聽UNIX域套接口)------> 調用 accept 方法等待遠程客戶端鏈接本服務器 ------> 當服務器程序接收到客戶端鏈接時 accept 方法返回客戶端鏈接網絡流(socket_stream) ------> 啓動一個線程處理這個客戶端鏈接。下面爲一個簡單的服務器程序:服務器

 

#include "acl_cpp/lib_acl.hpp"

// 處理客戶端鏈接的線程類
class client_thread : public acl::thread
{
public:
	client_thread(acl::socket_stream* client)
	: client_(client)
	{
	}

	~client_thread()
	{
		delete client_;
	}

protected:
	// 實現基類 acl::thread 中定義的純虛方法
	void* run()
	{
		acl::string buf;
		while (true)
		{
			// 從客戶端鏈接讀一行數據,第二個參數爲 false 意思是但願
			// socket_stream 在讀到一行數據時保留 \r\n
			if (client_->gets(buf, false) == false)
				return NULL;

			printf("gets one line: %s", buf.c_str());

			// 回寫所讀到的一行數據
			if (client_->write(buf) == -1)
				return NULL;
		}
	}

private:
	acl::socket_stream* client_;
};

int main(void)
{
	const char* addr = "0.0.0.0:8080";
	acl::socket_server server;

	// 監聽本機網絡地址
	if (server.open(addr) == false)
	{
		printf("listen addr: %s error: %s\r\n", addr, acl::last_serror());
		return -1
	}

	while (true)
	{
		// 等待客戶端鏈接本服務器程序
		acl::socket_stream* client = server.accept();
		if (client == NULL)
		{
			printf("accept error: %s\r\n", acl::last_serror());
			return -1;
		}

		// 建立一個子線程用來處理該客戶端鏈接
		client_thread* thread = new client_thread(client);

		// 將線程設爲分離模式,這樣當線程退出時會自行釋放線程相關資源
		thread->set_detachable(true);

		// 啓動該線程
		thread->start();
	}

	return 0;
}

       上面例子很是簡單,毋庸詳述,關於如何使用 acl 編寫多線程程序,請參照:使用 acl_cpp 庫編寫多線程程序。下面再給出一個簡單的網絡客戶端例子:網絡

#include "acl_cpp/lib_acl.hpp"

int main(void)
{
	const char* server_addr = "127.0.0.1:8080";
	int   conn_timeout = 10 /* 鏈接服務器超時時間,單位:秒 */
	int   rw_timeout = 10 /* 網絡 IO 超時時間,單位:秒 */;
	acl::socket_stream conn;

	// 鏈接遠程服務器
	if (conn.open(server_addr, conn_timeout, rw_timeout) == false)
	{
		printf("connect server: %s error: %s\r\n",
			server_addr, acl::last_serror());
		return -1;
	}

	const char* req = "hello world!\r\n";

	acl::string buf;

	// 向服務器寫一行數據,同時從服務器讀一行數據,循環 10 次
	for (int i = 0; i < 10; i++)
	{
		// 向服務器發送一行數據
		if (conn.write(req, strlen(req)) == -1)
		{
			printf("write request to server error: %s\r\n",
				acl::last_serror());
			return -1;
		}

		// 從服務器讀一行數據,注:第二個參數爲默認的 true,意思是得到
		// 一行數據後自動將尾部的 \r\n 去掉
		if (conn.gets(buf) == false)
		{
			printf("gets one line from server error: %s\r\n",
				acl::last_serror();
			return -1;
		}

		printf("response: %s\r\n", buf.c_str());
	}

	return 0;
}

 

 

   參考連接:多線程

   技術博客:http://zsxxsz.iteye.com/框架

   download:http://sourceforge.net/projects/acl/socket

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

   github:https://github.com/zhengshuxin/acl.net

 

      QQ 羣:242722074線程

相關文章
相關標籤/搜索