- C++开发者如何使用Swoole
- 编译libswoole.so
- 编译libswoole_cpp.so
- 编写程序
C++开发者如何使用Swoole
PHP编写的Server程序在某些情况下表现会较差
- 内存占用敏感的场景,PHP底层使用内存结构
zval来管理所有变量,会额外占用内存,如一个int32的整数可能需要占用16(PHP7)或24字节(PHP5)的内存,而C/C++只需要4字节。如果系统需要存储大量整数,占用的内存会非常大。 - PHP是动态解释执行的,计算性能较差,纯运算的代码可能会比C/C++程序差几十甚至上百倍。此类场景下不适合使用PHP
C/C++的支持弥补了这些不足,在上述场景下可以使用c-swoole或者cpp-swoole来编写Server程序。
cpp-swoole是对c-swoole的面向对象封装,支持了绝大部分swoole_server的特性包括task功能,另外还支持高精度定时器特性。
cpp-swoole依赖libswoole.so,需要先编译c-swoole生成libswoole.so
编译libswoole.so
git clone https://github.com/swoole/swoole-src.gitphpize./configurecmake .#cmake -DCMAKE_INSTALL_PREFIX=/opt/swoole .sudo make install
编译安装好libswoole.so后就可以下载cpp-swoole源码,编译libswoole_cpp.so
编译libswoole_cpp.so
git clone https://github.com/swoole/cpp-swoole.gitcmake .makesudo make install
编写程序
头文件:
#include <swoole/Server.hpp>#include <swoole/Timer.hpp>
服务器程序只需要继承swoole::Server,并实现响应的回调函数即可。
#include <swoole/Server.hpp>#include <swoole/Timer.hpp>#include <iostream>using namespace std;using namespace swoole;class MyServer : public Server{public:MyServer(string _host, int _port, int _mode = SW_MODE_PROCESS, int _type = SW_SOCK_TCP) :Server(_host, _port, _mode, _type){serv.worker_num = 4;SwooleG.task_worker_num = 2;}virtual void onStart();virtual void onShutdown() {};virtual void onWorkerStart(int worker_id) {}virtual void onWorkerStop(int worker_id) {}virtual void onPipeMessage(int src_worker_id, const DataBuffer &) {}virtual void onReceive(int fd, const DataBuffer &data);virtual void onConnect(int fd);virtual void onClose(int fd);virtual void onPacket(const DataBuffer &data, ClientInfo &clientInfo) {};virtual void onTask(int task_id, int src_worker_id, const DataBuffer &data);virtual void onFinish(int task_id, const DataBuffer &data);};void MyServer::onReceive(int fd, const DataBuffer &data){swConnection *conn = swWorker_get_connection(&this->serv, fd);printf("onReceive: fd=%d, ip=%s|port=%d Data=%s|Len=%ld\n", fd, swConnection_get_ip(conn),swConnection_get_port(conn), (char *) data.buffer, data.length);int ret;char resp_data[SW_BUFFER_SIZE];int n = snprintf(resp_data, SW_BUFFER_SIZE, (char *) "Server: %*s\n", (int) data.length, (char *) data.buffer);ret = this->send(fd, resp_data, (uint32_t) n);if (ret < 0){printf("send to client fail. errno=%d\n", errno);}else{printf("send %d bytes to client success. data=%s\n", n, resp_data);}DataBuffer task_data("hello world\n");this->task(task_data);// this->close(fd);}void MyServer::onConnect(int fd){printf("PID=%d\tConnect fd=%d\n", getpid(), fd);}void MyServer::onClose(int fd){printf("PID=%d\tClose fd=%d\n", getpid(), fd);}void MyServer::onTask(int task_id, int src_worker_id, const DataBuffer &data){printf("PID=%d\tTaskID=%d\n", getpid(), task_id);}void MyServer::onFinish(int task_id, const DataBuffer &data){printf("PID=%d\tClose fd=%d\n", getpid(), task_id);}void MyServer::onStart(){printf("server start\n");}class MyTimer : Timer{public:MyTimer(long ms, bool interval) :Timer(ms, interval){}MyTimer(long ms) :Timer(ms){}protected:virtual void callback(void);int count = 0;};void MyTimer::callback(){printf("#%d\thello world\n", count);if (count > 9){this->clear();}count++;}int main(int argc, char **argv){MyServer server("127.0.0.1", 9501, SW_MODE_SINGLE);server.listen("127.0.0.1", 9502, SW_SOCK_UDP);server.listen("::1", 9503, SW_SOCK_TCP6);server.listen("::1", 9504, SW_SOCK_UDP6);server.setEvents(EVENT_onStart | EVENT_onReceive | EVENT_onClose | EVENT_onTask | EVENT_onFinish);server.start();}
