1. 程式人生 > >boost庫在工作(39)網路UDP非同步服務端之九

boost庫在工作(39)網路UDP非同步服務端之九

前面建立的UDP伺服器和客戶端,都是同步的方式,也就是說當接收資料時,不能參與別的事情執行的。如果在一個只有介面執行緒的程式裡,又不想建立多執行緒,導致複雜程度的增加,在這種情況之下,我們還有一個方案可以選擇,就是建立一個非同步的UDP伺服器或客戶端,這樣既有單執行緒的簡單性,也可以讓客戶隨便操作介面的快速響應的特性。在boost庫裡使用io_service物件來實現非同步是輕而易舉的事情,因為封裝的介面簡單、明瞭。具體的程式碼如下:

// boost_028.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <ctime>

#include <boost/asio/ip/tcp.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/array.hpp>

#include <iostream>
#include <string>

//使用UDP名稱空間
using boost::asio::ip::udp;

//把當前時間轉換為字串。
std::string make_daytime_string()
{
	using namespace std; //為了使用time_t, time 和 ctime;
	time_t now = time(0);
	return ctime(&now);
}

//
//建立一個非同步UDP的時間伺服器。
//軟體開發人員: 蔡軍生  2013-08-25 
//QQ: 9073204
//
class UdpTimeServer
{
public:
	//傳入IO服務,然後建立一個UDP的SOCKET,IPV4版本,端號為13
	UdpTimeServer(boost::asio::io_service& ioService)
		:m_sockUdp(ioService,  udp::endpoint(udp::v4(), 13))
	{
		//進入接收服務中。
		RecvTime();
	}
private:
	//接收收客戶端的請求。
	void RecvTime(void)
	{
		//非同步接收資料
		m_sockUdp.async_receive_from(
			boost::asio::buffer(m_recvBuf), m_endpointRemote,
			boost::bind(&UdpTimeServer::handleRecvTime, this,
			boost::asio::placeholders::error,
			boost::asio::placeholders::bytes_transferred));
	}

	//當收到客戶端資料時,就進入本函式響應處理
	void handleRecvTime(const boost::system::error_code& error,
		std::size_t /*bytes_transferred*/)
	{
		//如果沒有出錯,就把時間字串傳送給客戶端。
		if (!error || error == boost::asio::error::message_size)
		{
			boost::shared_ptr<std::string> strMessage(
				new std::string(make_daytime_string()));

			m_sockUdp.async_send_to(boost::asio::buffer(*strMessage), m_endpointRemote,
				boost::bind(&UdpTimeServer::handleSendTime, this, strMessage,
				boost::asio::placeholders::error,
				boost::asio::placeholders::bytes_transferred));

			//接收下一次的資訊。
			RecvTime();
		}
	}

	//當傳送時間字串給客戶端成功之後響應。
	void handleSendTime(boost::shared_ptr<std::string> /*strMessage*/,
			const boost::system::error_code& /*error*/,
			std::size_t /*bytes_transferred*/)
	{

	}

private:
	udp::socket m_sockUdp; //伺服器的SOCKET。
	udp::endpoint m_endpointRemote; //收到資料時的端點資訊。
	boost::array<char, 1> m_recvBuf; //接收資料緩衝區。
};

void TestUdp(void)
{
	boost::asio::io_service ioService;
	UdpTimeServer udpTimeServer(ioService);
	ioService.run();
}


int _tmain(int argc, _TCHAR* argv[])
{
	//
	TestUdp();

	return 0;
}

在這個例子裡,主要封裝了一個伺服器UdpTimeServer,它是採用io_service物件和socket物件的非同步特性來構造,有事件響應之後才去執行相應的操作,不過這樣比前面的同步方式,還是複雜了一些,但帶來了避免多執行緒之間的同步問題。


相關推薦

boost工作39網路UDP非同步服務

前面建立的UDP伺服器和客戶端,都是同步的方式,也就是說當接收資料時,不能參與別的事情執行的。如果在一個只有介面執行緒的程式裡,又不想建立多執行緒,導致複雜程度的增加,在這種情況之下,我們還有一個方案可以選擇,就是建立一個非同步的UDP伺服器或客戶端,這樣既有單執行緒的簡單性

boost工作35網路服務

在前面的例子裡,只是處理每個連線發來的訊息,然後再把訊息轉回自己的那裡,跟別的連線沒有什麼關聯,這種情況只會適應一種像HTTP的那樣,只關心自己的東西。但在網路伺服器裡,最多的是跟別人有關聯的服務。比如說聊天室,就是不斷地把所有進入這個聊天室的人的訊息向所有人廣播出去,也就是

boost工作36網路服務

在上面介紹了管理所有連線的類,這個類主要就是新增新的連線,或者刪除不需要的連線。但是管理的類CAllConnect是沒有辦法知道什麼時候新增,什麼時候刪除的,它需要從接收到連線類裡獲取得到新的連線,從連線類裡獲得刪除的事件。如下面的程式碼://封裝一個服務端類來處理網路。 /

boost工作33網路服務

在這個例子裡,表示伺服器與一個客戶端的溝通渠道,就是一個連線,封裝為類CConnect。它是當伺服器接收到一個客戶端連線請求之後建立的,主要用來就是管理這個連線的生命週期,以及資料的接收和傳送。從生命週期上來說,當一個連線建立時就旦生了,那什麼時候死亡呢?在這個類的設計上是非

Java Socket應用 基於UDP的Socket通訊客戶

UDPClient.java package com.yijia; import java.io.IOException; import java.net.*; /** * 建立時間:2018/10/4 15:44 * 作者: * 郵箱:[email p

nginx iocp2udp非同步接收

   nginx的域名解析器使用已連線udp(收發前先呼叫ngx_udp_connect)傳送dns查詢、接收dns響應,如上篇tcp非同步連線所講,iocp需要先投遞udp的接收操作,才能引發接收完成的事件,因此要對域名解析器和udp非同步接收作些改進。 傳送後投遞     dns查詢由

小白學 Python 爬蟲39: JavaScript 渲染服務 scrapy-splash 入門

人生苦短,我用 Python 前文傳送門: 小白學 Python 爬蟲(1):開篇 小白學 Python 爬蟲(2):前置準備(一)基本類庫的安裝 小白學 Python 爬蟲(3):前置準備(二)Linux基礎入門 小白學 Python 爬蟲(4):前置準備(三)Docker基礎入門 小白學 Pyth

單目跟蹤位姿產品研發----socket通訊建立服務、客戶實戰

        由於客戶自己有伺服器,希望把顯示介面放在他們自己的伺服器上執行,而我們的視覺處理模組則放在自己的硬體中,兩部分獨立出來。為此,我將視覺處理模組寫成服務端工作站的模式,可以實現多個客戶端與之通訊。下圖是socket通訊的流程圖。 下

Spring Cloud Eureka原理分析:註冊過程-服務

Eureka的官方文件和Spring Cloud Eureka文件都有很多含糊的地方,其他資料也不多,只有讀讀原始碼維持生活這樣子…… 本文將不會詳細介紹每個細節,而是講述一些關鍵的地方,便於查閱。 一些好的參考資料 對讓人一臉懵逼的region和zone的解釋 攜程對Eureka機制的剖析

OpenVPM系列圖文教程—— Windows下搭建服務、客戶配置

背景:公司移動APP需要使用吶網服務,就順便研究了一下各種搭建方式,廢話不說看教程! 本文測試環境 雲香港 ECS 1 核 1GB (新人2折) Windows server 2012 R2 Datacenter Intel® Xeon® CPU

Winsock3 編寫一個TCP服務

本章介紹如何編寫一個 Winsock TCP/IP服務端來接收客戶連線請求 通訊分為面向連線通訊(Connection-Oriented Communication 如TCP)和非連線通訊(Connectionless Communication 如UDP)。筆

Webservice實踐基於CXF的服務開發

本節將實踐目前最流行的第二種web service 釋出和除錯框架  CXF Apache CXF 是一個開放原始碼框架,提供了用於方便地構建和開發 Web 服務的可靠基礎架構。它允許建立高效能和可擴

CAS 5.1.x 的搭建和使用—— 通過Overlay搭建服務-其它配置說明

#STEP 3 在TOMCAT8.5中跑一個模板然後將其war包中解壓出來的的application.properties複製出來,放到手動建立的src下的resources裡面 ## # CAS Server Context Configuration # server.context-path=/cas

微信小程式開發圖片上傳+服務接收

上次介紹了小程式開發中的微信登入。文章: 微信小程式開發(一) 微信登入流程, 這次介紹下小程式當中常用的圖片上傳。 前幾天做了圖片上傳功能,被坑了一下。接下來我們來看一下微信的上傳api。 這裡的filePath就是圖片的儲存路徑,型別居然是個

ABP開發框架前後開發系列---15ABP框架的服務和客戶快取的使用

快取在一個大型一點的系統裡面是必然會涉及到的,合理的使用快取能夠給我們的系統帶來更高的響應速度。由於資料提供服務涉及到資料庫的相關操作,如果客戶端的併發數量超過一定的數量,那麼資料庫的請求處理則以爆發式增長,如果資料庫伺服器無法快速處理這些併發請求,那麼將會增加客戶端的請求時間,嚴重者可能導致資料庫服務或者應

Nacos原始碼分析Nacos服務註冊示例流程

  上回我們講解了客戶端配置好nacos後,是如何進行註冊到伺服器的,那我們今天來講解一下伺服器端接收到註冊例項請求後會做怎麼樣的處理。   首先還是把博主畫的原始碼分析圖例發一下,讓大家對整個流程有一個大概的理解:圖示流程地址:https://www.processon.com/view/link/5f7e

基於c++的網路開發boost.Asio學習 Ubuntu安裝boost以及問題解決

執行環境:Ubuntu 12.04   版本: boost 1.68 下載網址:http://sourceforge.net/projects/boost/files/boost/1.58.0/boost_1_58_0.tar.bz2/download

boost工作13繫結器與函式物件之一

有一天,有一個同事過來問我,有沒有辦法把兩個引數變成一個引數,然後傳送給STL的演算法模板使用。我想了一下,要把兩個引數變成一個引數,只有一個辦法,就是使用繫結器。其實繫結器就是把兩個或兩個以上的引數變成一個引數,也就是變成函式物件的方式。在STL模板庫裡提供兩個繫結器:bi

boost工作9引用計數的智慧指標shared_ptr

接著下來,需要演示一下怎麼樣在多個物件裡共享一個物件,而不管每個物件的生命週期,就可以及時地把使用的物件在合適地方刪除。下面的例子裡先定義兩個類,然後每個類都引用共享的物件,接著使用完成後,就會在解構函式裡刪除,可以從例子程式執行的輸出結果看到內部執行的生命週期。有了共享智慧

boost工作1 使用陣列智慧指標scoped_array

C++裡陣列指標與一般的指標是有區別的。比如使用陣列形式分配的記憶體,就需要使用陣列的形式刪除。但初學開發的開發人員,往往會忘記這點,在我過去10多年的軟體程式碼審查過程裡,經常發現這點,如下面所示: char*  pBuf = new char[256]; ......