Simple Chat Using WebSocket and PHP Socket

The WebSocket is a feature of HTML5 for establishing a socket connections between a web browser and a server, once the connection has been established with the server, all WebSocket data (frames) are sent directly over a socket rather than usual HTTP response and requests, giving us much faster and persistent communication between a web browser and a server. Let’s create a simple chat system using this cool technology (HTML5 WebSocket and PHP).

WebSocket Chat

Browser Support

Old browsers do not support WebSockets, you need latest browser that supports HTML5 WebSocket features, Please see caniuse.com to find-out all WebSocket supported browsers.

Getting Started with WebSocket

Client side WebSocket implementation is very easy, the entire code consist of few methods and events. Have a look at code below for example.

1
2
3
4
5
6
7
8
//create a new WebSocket object.
websocket = new WebSocket("ws://localhost:9000/daemon.php");
websocket.onopen = function(evt) { /* do stuff */ }; //on open event
websocket.onclose = function(evt) { /* do stuff */ }; //on close event
websocket.onmessage = function(evt) { /* do stuff */ }; //on message event
websocket.onerror = function(evt) { /* do stuff */ }; //on error event
websocket.send(message); //send method
websocket.close(); //close method

To open the socket connection, we simply call new WebSocket(ws://SERVER URL), since WebSocket uses a different protocol for the connections, we use ws:// instead of http://, followed by host, port number and daemon script in your server:

url-breakdown

Right after opening the connection, we need to attach some event handlers that let us know status of connectivity, errors and incoming messages, for your references:

  • WebSocket(wsUri) — creates a new WebSocket object.
  • .onopen — Event occurs when connection is established.
  • .onclose — Event occurs when connection is closed.
  • .onmessage — Event occurs when client receives data from server.
  • .onerror — Event occurs when there is an error.
  • .send(message) — Transmits data to server using open connection.
  • .close() — Terminates existing connection.

You can implement WebSocket with jQuery support in your webpage like this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$(document).ready(function(){
    //Open a WebSocket connection.
    var wsUri = "ws://localhost:9000/daemon.php";  
    websocket = new WebSocket(wsUri);
   
    //Connected to server
    websocket.onopen = function(ev) {
        alert('Connected to server ');
    }
   
    //Connection close
    websocket.onclose = function(ev) {
        alert('Disconnected');
    };
   
    //Message Receved
    websocket.onmessage = function(ev) {
        alert('Message '+ev.data);
    };
   
    //Error
    websocket.onerror = function(ev) {
        alert('Error '+ev.data);
    };
   
     //Send a Message
    $('#send').click(function(){
        var mymessage = 'This is a test message';
        websocket.send(mymessage);
    });
});

Chat Page

As explained in examples above, we start by creating a WebSocket object, attaching event handlers and then using websocket.send() method to send the data. Since we are sending a collection of chat values, such as user name, message, color etc, we’ll convert our data to JSON format before sending to server.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
$(document).ready(function(){
    //create a new WebSocket object.
    var wsUri = "ws://localhost:9000/daemon.php";  
    websocket = new WebSocket(wsUri);
   
    websocket.onopen = function(ev) { // connection is open
        $('#message_box').append("<div class="system_msg">Connected!</div>"); //notify user
    }

    $('#send-btn').click(function(){ //use clicks message send button  
        var mymessage = $('#message').val(); //get message text
        var myname = $('#name').val(); //get user name
       
        if(myname == ""){ //empty name?
            alert("Enter your Name please!");
            return;
        }
        if(mymessage == ""){ //emtpy message?
            alert("Enter Some message Please!");
            return;
        }
       
        //prepare json data
        var msg = {
        message: mymessage,
        name: myname,
        color : '<?php echo $colours[$user_colour]; ?>'
        };
        //convert and send data to server
        websocket.send(JSON.stringify(msg));
    });
   
    //#### Message received from server?
    websocket.onmessage = function(ev) {
        var msg = JSON.parse(ev.data); //PHP sends Json data
        var type = msg.type; //message type
        var umsg = msg.message; //message text
        var uname = msg.name; //user name
        var ucolor = msg.color; //color

        if(type == 'usermsg')
        {
            $('#message_box').append("<div><span class="user_name" style="color:#"+ucolor+"">"+uname+"</span> : <span class="user_message">"+umsg+"</span></div>");
        }
        if(type == 'system')
        {
            $('#message_box').append("<div class="system_msg">"+umsg+"</div>");
        }
       
        $('#message').val(''); //reset text
    };
   
    websocket.onerror   = function(ev){$('#message_box').append("<div class="system_error">Error Occurred - "+ev.data+"</div>");};
    websocket.onclose   = function(ev){$('#message_box').append("<div class="system_msg">Connection Closed</div>");};
});

Below is our HTML for the chat system, it comes with some basic styling, I have not included the CSS part here, but you should find it in sample file.

1
2
3
4
5
6
7
8
<div class="chat_wrapper">
<div class="message_box" id="message_box"></div>
<div class="panel">
<input type="text" name="name" id="name" placeholder="Your Name" maxlength="10" style="width:20%"  />
<input type="text" name="message" id="message" placeholder="Message" maxlength="80" style="width:60%" />
<button id="send-btn">Send</button>
</div>
</div>

Chat Server using PHP Socket

Ok! Now we have our chat page ready to connect to server, but we also need to create a WebSocket server that runs permanently (no time-outs), performs WebSocket handshaking, send/receive data from chat page and handles multiple clients, for that we will create a daemon script in PHP. Everyone knows PHP is mostly used to create dynamic webpages, but most of us didn’t know that we can also create daemons (that run in the background) using nothing but PHP.

Install WebSocket Server
Install a local web server such as WAMP or XAMPP. I am using XAMPP server on Win-XP, it lets me use shell option to start my daemon script. I am not sure if WAMP has the same feature, but you can follow Dani’s solution here to run this server script. If you want to implement it on your website, first check whether your host allows you to run daemon scripts and shell commands.
Xampp Shell

PHP Socket Steps
We will be using PHP socket to create our WebSocket Chat server, Basically our PHP Chat server should do the following.

  1. Open a socket.
  2. Bind to a address.
  3. Listen incoming connections.
  4. Accept connections.
  5. WebSocket Handshake.
  6. Unmask/Encode data frames.

Open a socket:
First we create a socket with PHP socket_create(Domain, Type, Protocol) like this:

1
2
//Create TCP/IP sream socket and return the socket resource
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

Bind to a address:
Bind the name to the socket, this has to be done before a connection is established using socket_connect() or socket_listen().

1
2
// Bind the source address
socket_bind($socket, 'localhost');

Listen incoming connections:
Once the socket is created, we want our server to listen to incoming connection on that socket.

1
2
// Listen to incoming connection
socket_listen($socket);

Accept connections:
This function will accept incoming connections.

1
2
// Accept new connections
socket_accept($socket);

Handshake:
Client has to introduce itself by sending a WebSocket handshake request to establish a successful connection with server, a handshake request contains a Sec-WebSocket-Key a base64 encoded randomly generated 16-byte value. And the server reads the key, attaches magic string “258EAFA5-E914-47DA-95CA-C5AB0DC85B11”, hash key with SHA1, returns the key in Sec-WebSocket-Accept encoded with base64.
websocket-handshake-header
Handshake response with PHP :

1
2
3
4
5
6
7
8
9
$secKey = $headers['Sec-WebSocket-Key'];
$secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
$upgrade  = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"WebSocket-Origin: $host\r\n" .
"WebSocket-Location: ws://$host:$port/deamon.php\r\n".
"Sec-WebSocket-Accept:$secAccept\r\n\r\n";
socket_write($client_conn,$upgrade,strlen($upgrade));

Unmasking/Encoding data frames.
After the handshaking, client can now send and receive messages, but the messages sent are all encrypted, so if we want to display them, each data frame needs to be unmasked as described here

Starting Chat Server

It’s time to download the sample files by clicking download button below, you should find 2 PHP files, index.php and server.php. Using your Shell command-line interface in XAMPP, start WebSocket chat server by typing :

1
php -q c:\path-to-server\server.php

Once the server starts, you can navigate to index.php page using your browser and start test chatting.

Download

  1. Thank You for sharing such like helpful tutorial.
    Keep it up!!!

     Reply
  2. How can i make a single user conection? thanks

     Reply
  3. This is great. does it matter what port to use?

     Reply
  4. Brian Spaulding

    Bob. Wow. Thank you tremendously. Along with Sanwebe, who I assume produced this websocket implementation.

    I wouldn’t say ‘a tiny bug’ as it completely prevented pack from working for large messages, but perhaps a ‘tiny oversight’. Ha, the missing argument had me pulling my hair out as I use this websockets solution for showing phone activity. As the call queues increased, and certain conditions pushed the message size up… it was failing to pack. I just didn’t know why.

    Anyways, much obliged! Thank you for taking the time to provide that correction!!!!

     Reply
  5. Are you using a proxy?
    maybe you need add the ws:// as an exception

     Reply
    • No. No proxy. It did not work for a week, and then taken up all right as before. Technology mysteries …

  6. I tried to put live this chat application. Working fine

     Reply
  7. I get this error:

    “WebSocket connection to ‘ws://localhost:9000/demo/server.php’ failed: One or more reserved bits are on: reserved1 = 0, reserved2 = 1, reserved3 = 1”

     Reply
  8. How to create private chat message using above source code..

     Reply
  9. great examples!
    BUT i have a question…
    is it possible to write a mex only one specified client?
    thanx in advance

     Reply
  10. Hi, I got this error message after I tried with common line :

    Setting environment for using XAMPP for Windows.
    ACER@ACER-PC c:\xampp
    # php -q c:\xampp\htdocs\chat_socket\demo\server.php

    Warning: socket_bind(): unable to bind address [10013]: An attempt was made to a
    ccess a socket in a way forbidden by its access permissions.
    in C:\xampp\htdocs\chat_socket\demo\server.php on line 12

    Warning: socket_listen(): unable to listen on socket [10022]: An invalid argumen
    t was supplied.
    in C:\xampp\htdocs\chat_socket\demo\server.php on line 15

     Reply
  11. I have change the port to my default 80 in server.php and websocket url. Then I got the error when I tried to execute the command line of url.

    Setting environment for using XAMPP for Windows.
    ACER@ACER-PC c:\xampp
    # php -q c:\xampp\htdocs\chat_socket\demo\server.php

    could anyone help me please.
    Warning: socket_bind(): unable to bind address [10013]: An attempt was made to a
    ccess a socket in a way forbidden by its access permissions.
    in C:\xampp\htdocs\chat_socket\demo\server.php on line 12

    Warning: socket_listen(): unable to listen on socket [10022]: An invalid argumen
    t was supplied.
    in C:\xampp\htdocs\chat_socket\demo\server.php on line 15

     Reply
  12. Where this data can be store?
    and how can we connect it to database with user table ?

     Reply
  13. I have a question in mind as per the security is concern How much secure is that ?

     Reply
  14. Hello CodePlayer,

    I need a Help above code is working fine with non HTTPS site .. but when we try to use thos code With HTTPS server then its become fail.
    I would like to know the additional thing in this code “websocket = new WebSocket(“ws://localhost:9000/daemon.php”); ”

    I mean what else need to be done to connect with ssl encryption key(HTTPS) website..??
    Any help appreciated :)

     Reply
  15. Hello, I would like to know how to use websocket with https, because I installed the digital certificate of LetsEncrypt changed my host to use the “wss”:
    [websocket = new WebSocket (“ws: //191.101.11.23: 9003 / server. php ‘);
    but it is showing the following error:
    WebSocket connection to ‘wss: //191.101.11.23: 9003 / server.php’ failed: Error in connection establishment: net :: ERR_SSL_PROTOCOL_ERROR

    Please help me solve this problem.

     Reply
  16. thanks for good material. but . it does not work with me .it saying

    error occured undefined
    connection close

     Reply
  17. Going to integrate in my site. Hopefully this should work.

     Reply
  18. is there way to get online/active user in this socket script

     Reply
  19. Hi dears.
    I use MVC in my project and I need to use this stuff in it. But I want to use the class as server and use some functions in that class to have connection to database for saving the comments on it. But I cant do this. Can everybody help me please..
    This problem makes me crazy.

     Reply
  20. Error Occurred – undefined
    Connection Closed

    this msg ae showing on ?
    and msg does’t send or recived
    Why??

     Reply
    • I think you didn’t run the server. You should execute this command in cmd and after that you can run your project.
      the command : php -q C:/wamp/www/directchat/server.php

      After executing this command your server will start.

    • Hi,

      How do you go about continuously running the server once you’ve exited out of shell?

    • Hi Alana, I could be wrong but I believe that if you are using a unix/linux environment you can use nohup command before calling the php executable…

      e.g. instead of:

      “php -q C:/wamp/www/directchat/server.php”
      use
      “nohup php -q C:/wamp/www/directchat/server.php”

    • I have two questions,

      1. How do you run two one-on-one chat at the same time
      2. How do you close a connection after finishing the chat

  21. in my local it working fine
    but server it does not work is there any server setting required ?

     Reply
  22. Showing connected but not sending message, i.e. websocket.send(JSON.stringify(msg)); not working

     Reply
  23. Merci pour les informations très utile, Merci

     Reply
  24. Does this require the PHP websockets extension? My ISP doesn’t support that in the account type I have with them. Thanks.

     Reply
  25. Hi,
    thanks for the great tutorial.
    I have a problem; I think I have also found where the problem is but I don’t know how to solve it (I’m really not a programmer).
    It happens that if I’m typing a message, if another message come from another user my message input box is reset.
    I think the error is here:

    1
    2
    3
    4
    5
    6
    websocket.onmessage = function(ev) {
    ...
    ...
    ...
    $('#message').val(''); //reset text
    };

    Probably this shoul reset only if the message received is by me (it means I sent the message and I don’t need this in the message box anymore).
    Am I right?
    Possible solution is not to reset the field, but maybe a better solution is possible. Any help?
    Thank you.

     Reply
    • Few minutes after writing I found a better solution.
      Moved

      1
      $('#message').val(''); //reset text

      at the end of the fonction

      1
      $('#send-btn').click(function(){
  26. This forum doesn’t take char gt! It took even one whole line off.
    So my comment is unusable :))

     Reply
  27. Well done! The simpliest server I’ve ever seen.

    You have a very tiny bug there:
    pack(‘CCNN’, $b1, 127, $length);
    says:
    pack(): Type N: too few arguments
    should be:
    pack(‘CCNN’, $b1, 127,0, $length);

    You could get rid of one if in:
    elseif ($length > 125 && $length < 65536)
    just by switching the lines like this:
    if ($length = 65536) $header = pack(‘CCNN’, $b1, 127, $length);
    else header = pack(‘CCn’, $b1, 126, $length);

    R

     Reply
  28. Hi..
    You r Example is nice and really helps me.
    But, this example is not work in other PC in LAN. i.e. It is work only in my computer.

     Reply
  29. I tried to put live this chat application. Working fine.

    But it is not working where we use cyberroam program.
    How can I make it work even on network having cyberroam?
    It has something to do with port? Is there any port alter native to 9000?

     Reply
Message Type : Question Comment ?
  • Question : Can include code, jsFiddle, codePen etc using Markdown Syntax.
  • Comment : Short comments and questions.

 Notify me of followup comments via e-mail. You can also subscribe without commenting.

Ask a QuestionIf you have issue related to this topic, Please ask here.
Session leading to undefined index?
Ann asked 17 hours ago
4 views0 answers0 votes
remove cookie page
Mahdiyar asked 18 hours ago
3 views0 answers0 votes
Session leading to undefined index?
Ann asked 18 hours ago
5 views0 answers0 votes
Main box checked if all others manually checked.
Saran answered 18 hours ago
12 views1 answers0 votes
Response
Dikum asked 2 days ago
4 views0 answers0 votes
Issue Creating Shoutbox with jQuery & PHP Facebook Style
Saran answered 5 days ago
25 views1 answers0 votes
How to check all item using a single check box?
Srabon asked 1 week ago
27 views0 answers0 votes
What is the use of RSS FEED ?
Roshani Khanna asked 2 weeks ago
30 views0 answers0 votes
I am getting error. Can anyone help me, please?
Khin asked 2 weeks ago
30 views0 answers0 votes
Specify exactly where the file is uploaded to
Saran answered 2 weeks ago
41 views1 answers0 votes