views:

1417

answers:

4

How can I write a real time chat using XAJAX and PHP?

In other words, is there a way to send xajax responses from the server to multiple clients? Or is the only possibility to check for new messages every few seconds on client side?

+1  A: 

As long as there there is not HTTP push technology you will never get a realtime chat only using JavaScript.

Possible workarrounds:

  • use a Flash Movie or a Java Applet to perform some socket communication
  • hold polling requests back on the server side for a few seconds
Hippo
You know that here are some real life examples of such things in PHP/JS? I am also writing one for my job, yes, it has it's limitations but it's not impossible. Even without push technology.
elcuco
realtime means for me realtime (except connection speed)... but you are right: there a lot of things outside that really feel like realtime...
Hippo
I believe the latter is the approach that Facebook Messenger uses. It's not necessarily as elegant as a conventional client-server approach, perhaps, but it gets the job done.
Rob
+4  A: 

Sure there is, but I don't think it'll be very efficient with many users. You can either do polling where each client polls the server to see if there are any new messages, or you could use the comet technique in which the server can push new messages to the clients - Check out the Comet plugin for XAJAX. How this would be implemented using XAJAX and PHP is beyond me, but here's how I would try to implement it.

Let each client connect to the server (login etc), then:

  1. For each message sent by a client (sender) update the message queue for client (receiver)
  2. Let client poll server for new messages in the queue / Push the new messages via comet.
  3. Update GUI if there are new messages.
  4. Rinse, lather, repeat

Using a true IM server like ejabberd could go a long way, be more efficient and allow your users to connect via desktop clients (if that's what you want). I'd probably use that as a backend, IOW ejabberd would be the server and PHP would be the client using XMPP in PHP, and act as a proxy for the webgui.

See also:
Google Techtalk on Gmail's chat feature (and scalability issues)

That's my $0.02

Hannson
+2  A: 

No. Clients must "poll" the server repeatadly.

I think the key here is to think interaction design. The trick is to fool the user into thinking that the chat is instant, but when in reality it updates once every 1 or 2 or 3 or 10 seconds.

Ideas:

1) When the user sends a message, show it directly in the chat and trigger a poll.

2) If a poll comes back with multiple messages from other users, don't add them all at once, actually add them over a period of 1-2 sec or so, with random spacing, making it look like they're coming in "instantly" and independently. (If a bunch of messages come in at once the user is very quick to realize that the chat updated there and then, and not continiously.)

3) If the user is idle for x amount of time. Drop the poll rate to once every 10sec or so.

4) If the user is active, ie sending a lot of messages, poll more often.

5) Have a static file for every channel that your write the time the chat last updated to. For instance file chat-teenfun-lastupdate.txt has the contents 1224934239 or whatever time format you prefer. Serve this file statically and let clients poll this file in order to check if the channel has updated, rather that calling chat-poll.php?ch=teenfun that does a dynamic check. Static files are served around 10-100 times faster, depending on the work involved for the dynamic script, and you're gonna need it when you get 250+ users polling.

Good luck and have fun!

/0

PS. Alternatively you could actually let clients do an ajax call to the server and keep them 'hanging'. That is you accept their request and pretend to start sending data back, but then you just pause. When something happends you finish the response with the approriate data. For this to work I believe you'd need to write your own HTTP-server though, that does this specifically, as you can't have 250 php processes hanging around in memory. Maybe Lighttpd could be used in this way somehow with that LUA cache mod. I don't know. Would be interesting though. Hell I gotta try it sometime :)

0scar
A: 

The best strategy I've seen is to do an AJAX request for messages and then restart that exact same request as soon as it finishes.

On the server side, make the script "stall" for 60 seconds or until a new message is received. This keeps the same connection open for a max of 60 seconds, but when a new message is received, it outputs it and stops immediately, prompting the client-side AJAX to open another connection.

This provides almost instant notification of new messages and is also much easier on the server than making a new connection every x seconds.

Andrew