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()waitForTerminationRequeststop()就行了。

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;
}

-

from:Blog.CSDN.net/Poechant

POCO库中文编程参考指南(10)如何使用TCPServer框架?的更多相关文章

  1. POCO库中文编程参考指南(11)如何使用Reactor框架?

    1 Reactor 框架概述 POCO 中的 Reactor 框架是基于 Reactor 设计模式进行设计的.其中由 Handler 将某 Socket 产生的事件,发送到指定的对象的方法上,作为回调 ...

  2. POCO库中文编程参考指南(8)丰富的Socket编程

    POCO库中文编程参考指南(8)丰富的Socket编程 作者:柳大·Poechant 博客:Blog.CSDN.net/Poechant 邮箱:zhongchao.ustc#gmail.com (# ...

  3. POCO库中文编程参考指南(4)Poco::Net::IPAddress

    POCO库中文编程参考指南(4)Poco::Net::IPAddress 作者:柳大·Poechant 博客:Blog.CSDN.net/Poechant 邮箱:zhongchao.ustc#gmai ...

  4. POCO库中文编程参考指南(3)Poco::Net::Socket

    POCO库中文编程参考指南(3)Poco::Net::Socket 作者:柳大·Poechant 博客:Blog.CSDN.net/Poechant 邮箱:zhongchao.ustc#gmail.c ...

  5. POCO库中文编程参考指南(2)基本数据类型(Poco/Types.h)

    POCO库中文编程参考指南(2)基本数据类型 作者:柳大·Poechant 博客:Blog.CSDN.net/Poechant 邮箱:zhongchao.ustc#gmail.com (# -> ...

  6. POCO库中文编程参考指南(1)总览

    POCO库中文编程参考指南(1)总览 作者:柳大·Poechant 博客:Blog.CSDN.net/Poechant 邮箱:zhongchao.ustc#gmail.com (# -> @) ...

  7. POCO库中文编程参考指南(5)Poco::Net::SocketAddress

    1 枚举 最大地址长度,这个与Poco::Net::IPAddress中的定义可以类比,不过这里指的是`struct sockaddr_in6 enum { MAX_ADDRESS_LENGTH = ...

  8. POCO库中文编程参考指南(6)Poco::Timestamp

    1 类型别名 三个时间戳相关的类型别名,TimeDiff表示两个时间戳的差,第二个是以微秒为单位的时间戳,第三个是以 100 纳秒(0.1 微妙)为单位的时间戳: typedef Int64 Time ...

  9. POCO库中文编程参考指南(9)Poco::Net::DNS

    1 Poco::Net::DNS namespace Poco { namespace Net { class Net_API DNS { public: static HostEntry hostB ...

随机推荐

  1. 如何在IntelliJ IDEA在线查看源码的API文档

    https://blog.csdn.net/IFollowRivers/article/details/81604463

  2. 【BZOJ3834】[Poi2014]Solar Panels 分块好题

    [BZOJ3834][Poi2014]Solar Panels Description Having decided to invest in renewable energy, Byteasar s ...

  3. Yii 框架 URL路径简化

    Yii 框架的訪问地址若不简化会让人认为非常繁琐.未简化的地址一般格式例如以下: http://localhost:80/test/index.php?r=xxx/xxx/xxx 若是带有參数会更复杂 ...

  4. shell执行lua脚本传参数

    #lua test.lua 2 5arg[0]= test.lua arg[1]= 2arg[2]= 5 if arg[1] and arg[1] == "2" then prin ...

  5. div中p标签自动换行

    只需要设置div的width属性,p标签加上word-break:break-word属性就会自动换行 ----------------2016.7.1-------------------- 今天在 ...

  6. GEO(地理信息定位)

    核心知识点: 1.GEO是利用zset来存储地理位置信息,可以用来计算地理位置之间的距离,也可以做统计: 2.命令:geoadd geopos geodist geohash georadius/ge ...

  7. 将socket通信实现多进程

    我们知道,使用TCP协议需要提前建立连接,这样就只能一对一的传输,但是这样感觉十分单一,如果实现一个服务器能同时和多个客户端同信了? 这里就需要用到多线程. 处理的不同之处就在于:每一个接进来的客户都 ...

  8. Node.js学习笔记(2):基本模块

    Node.js学习笔记(2):基本模块 模块 引入模块 为了编写可维护的代码,我们把很多函数分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式.在No ...

  9. 登录令牌 Token 介绍

     Token值介绍 token 值: 登录令牌.利用 token 值来判断用户的登录状态.类似于 MD5 加密之后的长字符串. 用户登录成功之后,在后端(服务器端)会根据用户信息生成一个唯一的值.这个 ...

  10. 2018年东北农业大学春季校赛 E wyh的集合 【数学】

    题目链接 https://www.nowcoder.com/acm/contest/93/F 思路 其实容易知道在两个不同集合里 假设元素个数 分别为 a b 然后对于第一个集合里的每一个元素 都可以 ...