[Solution] Error: Could Not Decode a Text Frame As Utf-8 Websocket

Hello guys, if you are facing a similar error like me while handling the WebSockets, you are at the perfect place.

Most of the people face the error of “Could Not Decode a Text Frame As Utf-8” in an earlier stage of learning WebSocket programming.

Whether you are coding in any language, it doesn’t matter because WebSocket is a universal way for bi-directional communication between client and server. I was trying to put my hands on WebSocket programming using PHP.

As I started sending data from server to client, I was not able to receive any messages from the server to my client. Even more, I checked the error.log file of apache server to check for any error in my WebSocket file. But I found nothing.

After that, I checked the Network requests using dev tools in chrome. And I found that the WebSocket was working fine, but I also found an error message at the message area in the WebSocket request.

Could Not Decode a Text Frame As Utf-8

My PHP WebSocket code was to read the data from the client and reply again with the same data with some prefix like “Hi”.

//Encode message for transfer to client.
function mask($text)
{
      $b1 = 0x80 | (0x1 & 0x0f);
      $length = strlen($text);

      if($length <= 125)
             $header = pack('CC', $b1, $length);
      elseif($length > 125 && $length < 65536)
             $header = pack('CCn', $b1, 126, $length);
      elseif($length >= 65536)
             $header = pack('CCNN', $b1, 127, $length);
      return $header.$text;
}

$result = socket_read($client, 1024000);
$response = "Hi ".$result;
socket_write($client, mask($response));

In the above code, I have made a mask() function to create a frame to send to the client via WebSocket. As we discussed earlier, WebSockets work in a fixed format, so masking a message before sending it to the client is essential.

After finding a bunch of links on google and many opensource communities I finally found the solution :D. The solution is quite easy and effortless to implement.

Solution

As we know masking a message is important before sending any message from the server to the client. Similarly unmasking a message is also important before processing it server-side. Otherwise you will see unwanted and unreadable characters at the server-side.

The problem with my code was that I sent a message from the client to the server. After that, I attached a prefix “Hi ” without unmasking it. Finally I masked it again and sent it to the client. A silly mistake…

As soon as I found an error I quickly add a new function in my WebSocket file to unmask the messages received from the client and it worked. After applying the solution my code new code looks as below.

//Unmask incoming framed message
function unmask($text) {
      $length = ord($text[1]) & 127;
      if($length == 126) {
             $masks = substr($text, 4, 4);
             $data = substr($text, 8);
      }
      elseif($length == 127) {
             $masks = substr($text, 10, 4);
             $data = substr($text, 14);
      }
      else {
             $masks = substr($text, 2, 4);
             $data = substr($text, 6);
      }
      $text = "";
      for ($i = 0; $i < strlen($data); ++$i) {
             $text .= $data[$i] ^ $masks[$i%4];
      }
      return $text;
}
//Encode message for transfer to client.
function mask($text)
{
      $b1 = 0x80 | (0x1 & 0x0f);
      $length = strlen($text);

      if($length <= 125) 
             $header = pack('CC', $b1, $length); 
      elseif($length > 125 && $length < 65536) 
             $header = pack('CCn', $b1, 126, $length); 
      elseif($length >= 65536)
             $header = pack('CCNN', $b1, 127, $length);
      return $header.$text;
}

$result = socket_read($client, 1024000);
$response = "Hi ".unmask($result);
socket_write($client, mask($response));

Conclusion

I hope the above article helps you to solve the mentioned error in socket programming. Socket programming is quite complex but important part of backend programming. Even more,  all the major web services are working on WebSockets. So keep exploring it and create something different.

Enjoy Debugging 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

Read previous post:
Failed to Execute ‘createObjectURL’ on ‘URL’
[Solved] Uncaught TypeError: Failed to Execute ‘createObjectURL’ on ‘URL’: No Function Was Found That Matched the Signature Provided

I was trying to do some experiments with video steam online and I found some documents about online video streaming....

Close