POCO庫中文程式設計參考指南(10)如何使用TCPServer框架?
POCO庫中文程式設計參考指南(10)如何使用TCPServer框架?
- Author: 柳大·Poechant(鍾超)
- Email: zhongchao.ustc@gmail.com
- Blog:Blog.CSDN.net/Poechant
- Date: April 21th, 2012
1 TCPServer 框架概述
POCO 庫提供TCPServer
框架,用以搭建自定義的 TCP 伺服器。TCPServer
維護一個連線佇列、一個連線執行緒池。連線執行緒用於處理連線,連線執行緒只要一空閒就不斷地從連線佇列中取連線並進行處理。一旦連線執行緒從連線佇列中取到一個連線,就會建立一個TCPServerConnection
連線物件,並且呼叫該物件的start()
方法,直到start()
方法返回,這個連線物件就被刪除了。
連線執行緒的數量是動態的,其取決於連線佇列中排隊的連線數。當然,你使用的時候可以設定連線佇列的最大容量,以防止在高併發應用的伺服器上出現連線太多而使連線佇列溢位的悲劇發生。當連線佇列滿了,卻還有新的連線到來時,新來的連線就會被立即悄無聲息地關閉。
現在我們總結一下,就是要有一個可執行的 TCP 服務應用程式(命名為PoechantTCPServer
),還有很多 TCP 連線(命名為PoechantTCPConnection
)。而這裡我們用到工廠模式(準確說是TCPServerConnectionFactory
要我們用的),所以還有一個PoechantTCPConnectionFactory
。
2 光說不練假把式
2.1 建立一個 PoechantTCPServer
或許你還不熟悉 POCO 中的 Application,沒關係,這不影響本文的敘述。下面先建立一個 ServerApplication 如下:
// PoechantTCPServer.h
#ifndef POECHANT_TCP_SERVER
#define POECHANT_TCP_SERVER
#include "Poco/Util/ServerApplication.h"
#include "Poco/Util/Application.h"
using Poco::Util::ServerApplication;
using Poco::Util::Application;
class PoechantTCPServer: public ServerApplication
{
public:
PoechantTCPServer() {}
~PoechantTCPServer() {}
protected:
void initialize(Application& self);
void uninitialize();
int main(const std::vector<std::string>& args)
};
#endif
這樣在呼叫啟動PoechantTCPServer
時,會先呼叫initialize
,然後呼叫main
,在main
結束後會呼叫uninitialize
。其實現很簡單:
// PoechantTCPServer.cpp
#include "PoechantTCPServer.h"
void PoechantTCPServer::initialize(Application& self)
{
ServerApplication::loadConfiguration();
ServerApplication::initialize(self);
}
void PoechantTCPServer::uninitialize()
{
ServerApplication::uninitialize();
}
int PoechantTCPServer::main(const std::vector<std::string>& args)
{
// 這個我們最後說
return Application::EXIT_OK;
}
2.2 PoechantTCPConnection
連線類的定義很簡單,建構函式要傳入一個 StreamSocket 和其他你需要的引數。
// PoechantTCPConnection.h
#ifndef POECHANT_TCP_CONNECTION_H
#define POECHANT_TCP_CONNECTION_H
#include "Poco/Net/TCPServerConnection.h"
#include "Poco/Net/StreamSocket.h"
#include <string>
class PoechantTCPConnection: public TCPServerConnection
{
public:
PoechantTCPConnection(const StreamSocket& s,
const std::string& arg1,
int arg2,
double arg3);
void run();
private:
std::string _arg1;
int _arg2;
double _arg3;
};
#endif
實現如下:
// PoechantTCPConnection.cpp
#include "PoechantTCPConnection.h"
#include "Poco/Util/Application"
#include "Poco/Timestamp.h"
#include "Poco/Exception.h"
#include "Poco/DateTimeFormatter.h"
PoechantTCPConnection(const StreamSocket& s, const std::string& arg1, int arg2, double arg3):
TCPServerConnection(s), _arg1(arg1), _arg2(arg2), _arg3(arg3)
{
}
void run()
{
Application& app = Application::instance();
// 日誌輸出連線的TCP使用者的地址(IP和埠)
app.logger().information("Request from " + this->socket().peerAddress().toString());
try
{
// 向客戶端傳送資料,這裡以傳送一個表示時間的字串為例
Timestamp now;
std::string dt(DateTimeFormatter::format(now, _format));
dt.append("\r\n");
socket().sendBytes(dt.data(), (int) dt.length());
}
catch (Poco::Exception& e)
{
app.logger().log(e);
}
}
2.3 PoechantTCPConnectionFactory
工廠模式不必多說,名字唬人,其實非常非常簡單(準確的說設計模式大部分名字都唬人,但大部分都很有用,設計模式本身並不牛B,能把設計模式抽象提煉出來成我們現在認為很簡單的這些模式的那幾個人很牛B)。具體如下:
// PoechantTCPConnectionFactory.h
#ifndef POECHANT_TCP_CONNECTION_FACTORY_H
#define POECHANT_TCP_CONNECTION_FACTORY_H
#include "Poco/Net/TCPServerConnectionFactory.h"
#include "Poco/Net/TCPServerConnection.h"
#include "Poco/Net/StreamSocket.h"
#include <string>
class PoechantTCPConnectionFactory: public TCPServerConnectionFactory
{
public:
PoechantTCPConnectionFactory(const std::string arg1, int arg2, double arg3)
: _arg1(arg1), _arg2(arg2), _arg3(arg3)
{
}
TCPServerConnection* createConnection(const StreamSocket& socket)
{
return new PoechantTCPConnection(socket, arg1, arg2, arg3);
}
private:
std::string arg1;
int arg2;
double arg3;
};
#endif
2.4 啟動
回頭來說PoechantTCPServer::main(const std::vector<std::string>& args)
,其過程就是建立一個繫結了地址的ServerSocket
,把它傳給TCPServer
,當然別忘了把工程物件也給你的TCPServer
傳一個。最後就start()
,waitForTerminationRequest
和stop()
就行了。
int PoechantTCPServer::main(const std::vector<std::string>& args)
{
unsigned short port = (unsigned short) config().getInt("PoechantTCPServer.port", 12346);
std::string format(config().getString("PoechantTCPServer.format",
DateTimeFormat::ISO8601_FORMAT));
// 1. Bind a ServerSocket with an address
ServerSocket serverSocket(port);
// 2. Pass the ServerSocket to a TCPServer
TCPServer server(new PoechantTCPConnectionFactory(format), serverSocket);
// 3. Start the TCPServer
server.start();
// 4. Wait for termination
waitForTerminationRequest();
// 5. Stop the TCPServer
server.stop();
return Application::EXIT_OK;
}
然後寫一個程式入口:
#include "PoechantTCPServer.h"
int main(int argc, char **argv)
{
return PoechantTCPServer().run(argc, argv);
}
3 寫一個 Client 測測
TCPServer 要用 TCP 的客戶端來測試。在 POCO 中有豐富的 Socket,其中 TCP 方式的 Socket 有:
Poco::Net::ServerSocket
Poco::Net::StreamSocket
Poco::Net::DialogSocket
Poco::Net::SecureServerSocket
Poco::Net::SecureStreamSocket
UDP 方式的 Socket 有:
Poco::Net::DatagramSocket
Poco::Net::MulticastSocket
一個 TCP 方式 Client 如下(這裡用了 while 迴圈,其實可以在收到資料後就關閉的)
#include <iostream>
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/SocketAddress.h"
#define BUFFER_SIZE 1024
using Poco::Net::SocketAddress;
using Poco::Net::StreamSocket;
int main (int argc, const char * argv[])
{
SocketAddress address("127.0.0.1", 12346);
StreamSocket socket(address);
char buffer[BUFFER_SIZE];
while (true)
{
if (socket.available())
{
int len = socket.receiveBytes(buffer, BUFFER_SIZE);
buffer[len] = '\0';
std::cout << "" << buffer << std::endl;
}
}
return 0;
}
-
轉載請著名來自柳大的CSDN部落格:Blog.CSDN.net/Poechant
-
相關文章
- POCO庫中文程式設計參考指南(11)如何使用Reactor框架?程式設計React框架
- POCO庫中文程式設計參考指南(9)Poco::Net::DNS程式設計DNS
- POCO庫中文程式設計參考指南(7)Poco::Net::DatagramSocket程式設計
- POCO庫中文程式設計參考指南(6)Poco::Timestamp程式設計
- POCO庫中文程式設計參考指南(3)Poco::Net::Socket程式設計
- POCO庫中文程式設計參考指南(1)總覽程式設計
- POCO庫中文程式設計參考指南(5)Poco::Net::SocketAddress程式設計
- POCO庫中文程式設計參考指南(4)Poco::Net::IPAddress程式設計iPad
- POCO庫中文程式設計參考指南(8)豐富的Socket程式設計程式設計
- POCO庫中文程式設計參考指南(2)基本資料型別(Poco/Types.h)程式設計資料型別
- 前端參考指南前端
- Hbase 中文參考指南 3.0 校對活動發車了~
- C標準庫參考指南系列譯文(10)stdarg.h
- Android程式碼規範參考指南Android
- BOOST庫 學習參考完全開發指南
- C標準庫參考指南系列譯文
- Spring Boot 2.0.2 參考指南(通用的應用程式屬性 ②)中文文件Spring Boot
- Global.asa程式設計完全參考手冊程式設計
- Elasticsearch 參考指南(介紹)Elasticsearch
- ACCPS2-03使用java實現資料庫程式設計考試試題參照Java資料庫程式設計
- ASP.NET中Cookie程式設計簡明參考ASP.NETCookie程式設計
- DOJO API 中文參考手冊API
- MySQL8-中文參考-三-MySql
- 國外APP介面設計參考APP
- SCJP考試指南(考試號310-065 中文)
- Spring Boot 參考指南(Hazelcast)Spring BootAST
- Spring Boot參考指南中文版–Chapter1.Spring Boot中文文件Spring BootAPT
- 【Linux網路程式設計-2】TcpServer類、TcpClient類Linux程式設計TCPServerclient
- Spring Boot 參考指南(使用RestTemplate呼叫REST服務)Spring BootREST
- 系統設計面試參考-設計Spotify系統面試
- Koa框架教程,Koa框架開發指南,Koa框架中文使用手冊,Koa框架中文文件框架
- 美食類網頁設計版式參考網頁
- 程式設計師如何參與創業程式設計師創業
- MySQL8-中文參考-三十二-MySql
- Oracle EBS 11.5.10 中文語言包安裝參考Oracle
- InnoDB 中文參考手冊 --- 10 multiversioning 的實現 (轉)
- Spring Boot 參考指南(目錄)Spring Boot
- Spring Boot 參考指南(Quartz Scheduler)Spring Bootquartz