🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 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 ---- ```shell git clone https://github.com/swoole/swoole-src.git phpize ./configure cmake . #cmake -DCMAKE_INSTALL_PREFIX=/opt/swoole . sudo make install ``` 编译安装好`libswoole.so`后就可以下载`cpp-swoole`源码,编译`libswoole_cpp.so` 编译libswoole_cpp.so ----- ```shell git clone https://github.com/swoole/cpp-swoole.git cmake . make sudo make install ``` 编写程序 ---- 头文件: ```c #include <swoole/Server.hpp> #include <swoole/Timer.hpp> ``` 服务器程序只需要继承`swoole::Server`,并实现响应的回调函数即可。 ```cpp #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(); } ```