Php persistent connection, playing is so simple
When talking about long links, you must be familiar with it, that is, reusing a link for continuous data interaction. Unlike those overnight services, the link needs to be opened and closed frequently, low efficiency also increases business complexity. Many Internet business scenarios require persistent connection support, such as games, chats, and Information Push. Today, we will reveal the php persistent connection method step by step. I believe that the implementation of any technology is based on the needs of business scenarios, so this time we will talk about things in the chat room.
0x00 scalpers
I remember using php to write chat rooms or using polling. Undoubtedly, when talking about polling, some people will say long polling. That's right! Long polling is also very good, but it is difficult to play this on nginx + fpm. After all, a request needs to occupy a php process (even if apache + php_mod is used, it also requires a request for a thread), so it would be okay for a few people to play casually. Once there are more people put online, this is basically useless. Therefore, we still adopt the polling method, so that the process will not be blocked and a request can be immediately responded, but the new problem is that we need to constantly send requests to the server, the larger the interval, the larger the message latency.
0x01 gorgeous Transformation
After experiencing the one-second, one-second, and three-second scenes! So I decided to become a real man. Oh no, it should be a real persistent connection. Fuck polling, fuck long polling, fuck webserver, all back to the edge station, let flash socket (or websocket) to rule the world! Start a long connection journey in the true sense. To use persistent connections, you always have to deal with sockets. As the best language in the world (none), socket encapsulation is indispensable. Just copy the socket _ *** and start it. So we have the following code. Is it a persistent connection? Latency, right? Socket, right? Medical Fee, right? So easy ....
- $sfd = socket_create(AF_INET, SOCK_STREAM, 0);
-
- socket_bind($sfd, "0.0.0.0", 1234);
-
- socket_listen($sfd, 511);
-
- socket_set_option($sfd, SOL_SOCKET, SO_REUSEADDR, 1);
-
- socket_set_nonblock($sfd);
-
- $rfds = array($sfd);
-
- $wfds = array();
-
- do{
-
- $rs = $rfds;
-
- $ws = $wfds;
-
- $es = array();
-
- $ret = socket_select($rs, $ws, $es, 3);
-
-
-
- //read event
-
- foreach($rs as $fd){
-
- if($fd == $sfd){
-
- $cfd = socket_accept($sfd);
-
- socket_set_nonblock($cfd);
-
- $rfds[] = $cfd;
-
- echo "new client coming, fd=$cfd\n";
-
- }else{
-
- $msg = socket_read($fd, 1024);
-
- if($msg <= 0){
-
- //close
-
- }else{
-
- //recv msg
-
- echo "on message, fd=$fd data=$msg\n";
-
- }
-
- }
-
- }
-
-
-
- //write event
-
- foreach($ws as $fd){
-
- socket_write($fd, ........);
-
- }
-
-
-
- }while(true);
0x02 peak Creation
From the day when I played socket, google told me in a few words that select should not be used in high concurrency; efficiency should be used; iocp should be used for win; epoll should be used for linux, blablablabla... oh! Well, Since google has said this, I cannot compete with his old man. I decided again (Why ?) I want to hear from google and get epoll up, but I can't write it on my own? The whole expansion is better for people like me, and libevent is leaving you! After the crazy co code (py), the masterpiece finally came out of the mountains. How efficient can it be, how much concurrency it can support, and how much concurrency it doesn't make? It's useless to select it anyway. I'm a hero!
- $sfd = stream_socket_server ('tcp://0.0.0.0:1234', $errno, $errstr);
-
- stream_set_blocking($sfd, 0);
-
- $base = event_base_new();
-
- $event = event_new();
-
- event_set($event, $sfd, EV_READ | EV_PERSIST, 'ev_accept', $base);
-
- event_base_set($event, $base);
-
- event_add($event);
-
- event_base_loop($base);
-
- function ev_accept($socket, $flag, $base)
-
- {
-
- $connection = stream_socket_accept($socket);
-
- stream_set_blocking($connection, 0);
-
- $buffer = event_buffer_new($connection, 'ev_read', NULL, 'ev_error', $connection);
-
- event_buffer_base_set($buffer, $base);
-
- event_buffer_timeout_set($buffer, 30, 30);
-
- event_buffer_watermark_set($buffer, EV_READ, 0, 0xffffff);
-
- event_buffer_priority_set($buffer, 10);
-
- event_buffer_enable($buffer, EV_READ | EV_PERSIST);
-
- }
-
- function ev_error($buffer, $error, $connection)
-
- {
-
- event_buffer_disable($buffer, EV_READ | EV_WRITE);
-
- event_buffer_free($buffer);
-
- fclose($connection);
-
- }
-
- function ev_read($buffer, $connection)
-
- {
-
- $read = event_buffer_read($buffer, 256);
-
- //do something....
-
- }
0x03 Best Practices
With the increase in the number of people and the increase in concurrency, a single process can no longer meet the demand. The story of Tian boguang tells us that single-picking is not a good fit for a group of P. Why? As the saying goes, things are trivial and stop !! If you don't want to change it, you will lose it. Split it up and split a single process into multiple processes. However, after the split, there are new problems, such as inter-process communication, Server Load balancer, and session uniqueness. Since such a problem has been raised, there must be a solution. There are extensions and libraries available to solve this problem, such as swoole and workerman? Compared with swoole, swoole is more powerful in nature and functions! It seems that the short form is not elegant. Well, the performance and functions are even better (bucket brother, please forgive me for being bored ~).... Wait !!! However, when we use php to develop the web, we do not use the library related to webserver for development, right? It's just a simple echo. All these complicated tasks are handed over to nginx or apache, which is the top of the list, so that we can concentrate on writing logic. For web writing, we only need to simply configure nginx and fpm. What about the socket service? Why can't we simply configure it like nginx + fpm ?? Of course yes, you must be able ..... I am afraid that the advertisement is coming...
0x04 unexpected
Writing a socket service is not more advanced than writing a web service. It is all about coding and completing requirements. The communication layer is fixed, but one is done by nginx and the other is done by yourself .. But now you don't need to do it yourself. Similar to the nginx + fpm solution, fooking + fpm = php persistent connection, gateway is used to carry the connection, router is used to forward messages, and inter-process communication? Load Balancing? Session unique? So easy ..
- $ Sid = $ _ SERVER ['sessionid']; // This is the SESSIONID
-
- $ Data = file_get_contents ("php: // input"); // you can get the request content.
-
- // Two steps are required to return the message
-
- Header ('content-Length: 11'); // number of bytes returned to the client
-
- Echo "hello world ";
-
- // Send messages to other users
-
- Include 'api. php ';
-
- $ Router = new RouterClient ('router host', 'router port ');
-
- $ Router-> sendMsg (User sessionid, "fuck you ");
-
- // You want to send messages to everyone
-
- $ Router-> sendAllMsg ("fuck all ");
-
- // Send messages to a specified group (similar to pub/sub of redis)
-
- $ Router-> publish ("channel name", "fuck all ");
Project address: http://git.oschina.net/scgywx/fooking
Document address (occasionally updated): http://my.oschina.net/scgywx/blog/465186