phphtmlchatroom

HTML5 simple chatroom


What I would like to do is a simple HTML5 chatroom, nothing fancy, once someone says something it sends it out to everyone currently connected to the server and that's it. No storage, nothing complex. It would have to be flexible, though, my site should be able to automatically create separate chatrooms as they're needed. I've seen a lot of demos and examples but all of them require me to install node.js or something similar that requires terminal access (which I do not have). I'm currently running on one of those free website hosts, that give you an ftp client, a mysql database, some php support and that's it. Is there any way of doing this? Or perhaps I'm missing something, is there a way to install packages on these kind of servers? Perhaps someone knows a way to obtain terminal access? Any kind of help would be greatly appreciated, thanks.


Solution

  • Been there done that. It's not trivial to get right.

    I think there's one important decision that you have to make: Do you want the chat to be really instantaneous, or is it ok to get like 2 second delays until everyone sees new messages.

    If delays are ok, you could really just poll the server every 2 seconds to see if new messages are available. Nobody likes delays, but depending on what you want to do, it might not be all that bad. The server would then check a database/file on every request and return updates. It's a very simple solution and it works. (And if you think polling every 2 seconds is wasting resources and an unnecessary load on the server... read on, the alternative might be worse.)

    A fully instantaneous chat requires that the server can immediately send new data to the clients, without waiting for the clients to ask for it. HTTP does not natively support this and if you don't want to use any Flash/Java, the only way I know to do this is using comet requests. These are requests (usually AJAX) that will deliberately hang for a while on the server and will then return precisely at the moment when new data is available that needs to be sent to the client, or when a timeout occurs. Every time a comet request returns, the client processes the data and immediately makes another comet request that will again hang until new data is available. I believe every chat website in pure HTML/JS does it this way (Omegle, Facebook, many others).

    Now, this was the easy part. But how do you implement this on the server? Let's look at this situation: You have 10 users in the chat, that means 10 clients that will each have a hanging comet request that waits for new data. One of the users writes something into the chat and that causes an additional request to the server to post the text. How do you make this one execution of a PHP script on the server cause the other 10 executions to stop waiting and return the new data? (You can substitue PHP with Perl, or anything.) You will need something that allows several executions of scripts to talk to each other. (Or the PHP code could itself be polling a database every second, but that again introduces delays.) Any form of inter-process communication (IPC) is difficult in those scripting languages, especially that you don't know what kind of model the web server uses to execute them. Apache for example can have a process for each request, or a thread for each request, or a mix of both. But maybe your hosting uses IIS, or something else, so it's difficult to do IPC in this situation. What I ended up doing was to create an own server component in PHP that was running all the time, its task was to pass messages between different executions of PHP scripts. And yes, this requires shell access. All PHP executions would connect to that server component via sockets and messages could be passed around. It was tricky to get right, but at the end it worked quite well.

    Unfortunately, comet requests can be very wasteful with memory and CPU cycles. My Apache server had a process-per-PHP-execution model. So when there were 100 people in the chat, that meant there were 100 pending comet requests at any time, meaning there were 100 Apache processes running. And even if a fresh Apache process uses only 10MB, that makes a total of 1GB! That's a lot of memory and those processes were nothing but waiting for something to happen. The chat was an incredible memory hog. Also, such a chat generates really a lot of requests: Every time someone says something in the chat, all 100 requests return and you will get 100 new requests right after that. Twice as many users in the chat usually means four times as many requests. And you'd really want this to be snappy. Apache wasn't always so efficient in handling this. There is some web server software around that is specially tuned toward comet requests and that will scale very well, but that again requires more access to the server than you have.

    So for completeness, here's the end of my story: In the meantime I ditched all the PHP and entirely rewrote the chat. In my opinion, Apache as well as PHP is highly unsuitable for this kind of task. There's now a single Java server component that integrates an efficient multi-threaded HTTP server. I have stress tested it and it behaves very well: With 500 spamming clients connected, CPU usage doesn't go over 15% and memory usage stays at 150MB. That's much better than I ever expected. Its responsiveness has improved a lot too, compared to Apache/PHP. The end result can be viewed at http://www.dark-chat.info/ Although the chat is currently somewhat dead for various reasons. That will hopefully change as I get more time for it.

    Well, I know this isn't helping you much at all, since you're quite restricted by your hosting provider. And without shell access, there's really only so much you can do. If you're ok with a 2 second delay (or make it 1 second) and you don't expect more than 20 users at the same time, you could really just go with the polling. There are ways to optimize this a bit, for example, active users can get 1 second polls and those that rarely write something get 5 second polls.

    That said, maybe you could also look around for some sort of hosted solution. I'm sure there are chats around that you can embed via iframes.

    Ok, this got much longer than I wanted to. But I hope it helps some people. :)