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

9 very useful traffic marketing software and tools

WeChat marketing promotion focuses on thinking an...

600 stores’ private live broadcasts summarized these 6 live broadcast methods!

With the popularity of the live streaming industr...

5000-word methodology: A complete guide to adding followers in private domains

How to accurately attract traffic in private doma...

Which self-media platforms are worth doing? Which self-media platform is better?

After working in self-media operation for a long ...

117 Epidemic Observation | Yan Ning·Prin·Ⅱ

The storm is coming, New Jersey has a curfew~ Wri...

What is the price of 2U server hosting configuration?

The main charging standard for server hosting is ...

2021 Bianfeng Weiweiwei talks about + research report highlights

Brief introduction of Bianfeng Weiweiweidaolai + ...

A complete guide to event operations! A must-see for operators!

Event operation is a job that most operations per...