• 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

    1. git clone https://github.com/swoole/swoole-src.git
    2. phpize
    3. ./configure
    4. cmake .
    5. #cmake -DCMAKE_INSTALL_PREFIX=/opt/swoole .
    6. sudo make install

    编译安装好libswoole.so后就可以下载cpp-swoole源码,编译libswoole_cpp.so

    编译libswoole_cpp.so

    1. git clone https://github.com/swoole/cpp-swoole.git
    2. cmake .
    3. make
    4. sudo make install

    编写程序

    头文件:

    1. #include <swoole/Server.hpp>
    2. #include <swoole/Timer.hpp>

    服务器程序只需要继承swoole::Server,并实现响应的回调函数即可。

    1. #include <swoole/Server.hpp>
    2. #include <swoole/Timer.hpp>
    3. #include <iostream>
    4. using namespace std;
    5. using namespace swoole;
    6. class MyServer : public Server
    7. {
    8. public:
    9. MyServer(string _host, int _port, int _mode = SW_MODE_PROCESS, int _type = SW_SOCK_TCP) :
    10. Server(_host, _port, _mode, _type)
    11. {
    12. serv.worker_num = 4;
    13. SwooleG.task_worker_num = 2;
    14. }
    15. virtual void onStart();
    16. virtual void onShutdown() {};
    17. virtual void onWorkerStart(int worker_id) {}
    18. virtual void onWorkerStop(int worker_id) {}
    19. virtual void onPipeMessage(int src_worker_id, const DataBuffer &) {}
    20. virtual void onReceive(int fd, const DataBuffer &data);
    21. virtual void onConnect(int fd);
    22. virtual void onClose(int fd);
    23. virtual void onPacket(const DataBuffer &data, ClientInfo &clientInfo) {};
    24. virtual void onTask(int task_id, int src_worker_id, const DataBuffer &data);
    25. virtual void onFinish(int task_id, const DataBuffer &data);
    26. };
    27. void MyServer::onReceive(int fd, const DataBuffer &data)
    28. {
    29. swConnection *conn = swWorker_get_connection(&this->serv, fd);
    30. printf("onReceive: fd=%d, ip=%s|port=%d Data=%s|Len=%ld\n", fd, swConnection_get_ip(conn),
    31. swConnection_get_port(conn), (char *) data.buffer, data.length);
    32. int ret;
    33. char resp_data[SW_BUFFER_SIZE];
    34. int n = snprintf(resp_data, SW_BUFFER_SIZE, (char *) "Server: %*s\n", (int) data.length, (char *) data.buffer);
    35. ret = this->send(fd, resp_data, (uint32_t) n);
    36. if (ret < 0)
    37. {
    38. printf("send to client fail. errno=%d\n", errno);
    39. }
    40. else
    41. {
    42. printf("send %d bytes to client success. data=%s\n", n, resp_data);
    43. }
    44. DataBuffer task_data("hello world\n");
    45. this->task(task_data);
    46. // this->close(fd);
    47. }
    48. void MyServer::onConnect(int fd)
    49. {
    50. printf("PID=%d\tConnect fd=%d\n", getpid(), fd);
    51. }
    52. void MyServer::onClose(int fd)
    53. {
    54. printf("PID=%d\tClose fd=%d\n", getpid(), fd);
    55. }
    56. void MyServer::onTask(int task_id, int src_worker_id, const DataBuffer &data)
    57. {
    58. printf("PID=%d\tTaskID=%d\n", getpid(), task_id);
    59. }
    60. void MyServer::onFinish(int task_id, const DataBuffer &data)
    61. {
    62. printf("PID=%d\tClose fd=%d\n", getpid(), task_id);
    63. }
    64. void MyServer::onStart()
    65. {
    66. printf("server start\n");
    67. }
    68. class MyTimer : Timer
    69. {
    70. public:
    71. MyTimer(long ms, bool interval) :
    72. Timer(ms, interval)
    73. {
    74. }
    75. MyTimer(long ms) :
    76. Timer(ms)
    77. {
    78. }
    79. protected:
    80. virtual void callback(void);
    81. int count = 0;
    82. };
    83. void MyTimer::callback()
    84. {
    85. printf("#%d\thello world\n", count);
    86. if (count > 9)
    87. {
    88. this->clear();
    89. }
    90. count++;
    91. }
    92. int main(int argc, char **argv)
    93. {
    94. MyServer server("127.0.0.1", 9501, SW_MODE_SINGLE);
    95. server.listen("127.0.0.1", 9502, SW_SOCK_UDP);
    96. server.listen("::1", 9503, SW_SOCK_TCP6);
    97. server.listen("::1", 9504, SW_SOCK_UDP6);
    98. server.setEvents(EVENT_onStart | EVENT_onReceive | EVENT_onClose | EVENT_onTask | EVENT_onFinish);
    99. server.start();
    100. }