Teach you to write a super simple swoole chat room in five minutes

Teach you to write a super simple swoole chat room in five minutes

I was originally planning to continue writing my multi-process tutorial, but today I suddenly wanted to take a look at swoole's websocket.

swoole-1.7.9 adds built-in websocket server support. With just a few lines of PHP code, you can write an asynchronous non-blocking multi-process WebSocket server.

swoole_websocket_server inherits from swoole_http_server. If the onRequest callback is set, the websocket server can also be used as an http server.

  1. $server = new swoole_websocket_server( "0.0.0.0" , 9501 );
  2.  
  3. $server->on( 'open' , function (swoole_websocket_server $server, $request) {
  4. echo "server: handshake success with fd{$request->fd}\n" ;
  5. });
  6.  
  7. $server->on( 'message' , function (swoole_websocket_server $server, $frame) {
  8. echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n" ;
  9. $server->push($frame->fd, "this is server" );
  10. });
  11.  
  12. $server->on( 'close' , function ($ser, $fd) {
  13. echo "client {$fd} closed\n" ;
  14. });
  15.  
  16. $server->start();

I looked at the demo on the official website and it seemed pretty simple.

  1. <? php  
  2. //Official website demo
  3. $ server = new swoole_websocket_server("0.0.0.0", 9501);
  4.  
  5. $server- > on('open', function (swoole_websocket_server $server, $request) {
  6. echo "server: handshake success with fd{$request- > fd}\n"; //$request- > fd is the client id
  7. });
  8.  
  9. $server- > on('message', function (swoole_websocket_server $server, $frame) {
  10. echo "receive from {$frame- > fd}:{$frame- > data},opcode:{$frame- > opcode},fin:{$frame- > finish}\n";
  11. $server- > push($frame- > fd, "this is server"); //$frame- > fd is the client id, $frame- > data is the data sent by the client
  12. //The server sends data to the client using $server- > push('client id', 'content')
  13. });
  14.  
  15. $server- > on('close', function ($ser, $fd) {
  16. echo "client {$fd} closed\n";
  17. });
  18.  
  19. $server- > start();

I just like this kind of simple and easy to understand demo. The meaning of each line of code can be understood at a glance.

The server is ready, I'll find some client js code

MDN for Firefox

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title></title>
  5. <meta charset= "UTF-8" >
  6. <script type= "text/javascript" >
  7. var exampleSocket = new WebSocket( "ws://0.0.0.0:9501" );
  8. exampleSocket.onopen = function (event) {
  9. exampleSocket.send( "Dear server! I'm connected to you!" );
  10. };
  11. exampleSocket.onmessage = function (event) {
  12. console.log(event.data);
  13. }
  14. </script>
  15. </head>
  16. <body>
  17. <input type= "text" id= "content" >
  18. <button onclick= "exampleSocket.send( document.getElementById('content').value )" >Send</button>
  19. </body>
  20. </html>

***The command line runs the php file, and then the browser opens the html file.

F12 opens the debugging interface and looks at the console. OK, no problem.

At this time, I suddenly thought of something, because in the tutorial on multi-process, the handles of all child processes were stored in the main process for later inter-process communication.

Then I will store all the client links into an array. Every time a client sends a message, I will iterate through the client array and send the message to the group. Has the chat room been realized soon?

Then, the server code looks like this

  1. <?php
  2. $map = array(); //Client collection  
  3. $server = new swoole_websocket_server( "0.0.0.0" , 9501 );
  4.  
  5. $server->on( 'open' , function (swoole_websocket_server $server, $request) {
  6. global $map; //Client collection  
  7. $map[$request->fd] = $request->fd; //***Save it when connected  
  8. });
  9.  
  10. $server->on( 'message' , function (swoole_websocket_server $server, $frame) {
  11. global $map; //Client collection  
  12. $data = $frame->data;
  13. foreach($map as $fd){
  14. $server->push($fd , $data); //Loop broadcast  
  15. }
  16. });
  17.  
  18. $server->on( 'close' , function ($ser, $fd) {
  19. echo "client {$fd} closed\n" ;
  20. });
  21.  
  22. $server->start();

Haha, I thought I was done, but I found out I was just being naive.

You can try it yourself. After running PHP, open two pages in the browser and see what the contents of console.log are.

It worked fine, but it didn't achieve the chat effect we were talking about.

Let’s find out the reason.

I first wanted to see what was in $map, so I outputted it and found that there was only one element in this map.

Oh, that's not right, this is a global variable. Shouldn't there be as many elements as there are client connections?

What's going on? Why aren't all client IDs saved?

At this point, I couldn't solve the problem of the map variable, so I wanted to see what the fd was.

As usual, var_dump output shows that fd is an int type number, and it is self-increasing.

This is easy, it's just numbers.

So, I do this.

I can't save the variable, I can't handle it, so I save it in text.

Final version of websocket.php

  1. <?php
  2.  
  3. $server = new swoole_websocket_server( "0.0.0.0" , 9501 );
  4.  
  5. $server->on( 'open' , function (swoole_websocket_server $server, $request) {
  6. file_put_contents( __DIR__ . '/log.txt' , $request->fd);
  7. });
  8.  
  9. $server->on( 'message' , function (swoole_websocket_server $server, $frame) {
  10. global $client;
  11. $data = $frame->data;
  12. $m = file_get_contents( __DIR__ . '/log.txt' );
  13. for ($i= 1 ; $i<= $m ; $i++) {
  14. echo PHP_EOL . ' i is ' . $i . ' data is ' .$data . ' m = ' . $m;
  15. $server->push($i, $data);
  16. }
  17.  
  18. });
  19.  
  20. $server->on( 'close' , function ($ser, $fd) {
  21. echo "client {$fd} closed\n" ;
  22. });
  23.  
  24. $server->start();

Open the HTML file again and observe the input on multiple pages. OK, it's OK.

Of course, as a chat room, what I wrote is too simple, you can write a better interface yourself (because I am too lazy to write the interface)

Also, each chat record should be saved, so that when a new connection comes, the previous chat record will be sent first. In this way, I think the experience will be better.

Then, everyone can have a pleasant chat. Haha

<<:  Cocos Play: The best solution for mobile web games

>>:  Apple releases iOS 9 fifth test, third public beta

Recommend

Why are konjac shreds white and konjac cubes black?

Audit expert: Wang Guoyi Postdoctoral fellow in N...

Lao Duan said: Traditional TV is to the left, online video is to the right

iQIYI's PPS has been leading the video websit...

Live streaming methods and strategies

The women's clothing category with a customer...

Detailed explanation of Tik Tok recommendation mechanism!

No matter where you are, if you want to make mone...

How to use custom menus in WeChat Enterprise Account Development

Each application in the enterprise account can ha...

Samsung to produce self-driving chips for Tesla

Recently, according to foreign media reports, Sam...

How to get information on Baidu Aicaigou?

We have reached a strategic cooperation with Baid...

Groundwater storage is not just about “storing water”

groundwater It is an important component of water...

Search for OCPC practical strategy full interpretation

What rules does the optimization adjustment of se...