Sockets in PHP; Chat with multiple rooms: how to?
Moderator: General Moderators
Sockets in PHP; Chat with multiple rooms: how to?
Hi all,
I have written a multiplayer online game that includes a chat. The backend is a PHP script on the server. Players are connected to the game via PHP sockets. The game contains a chat, which I am mentioning because it is the best-known application for this sort of stuff. It all runs stable as long as there is only one group of people playing. But I want several games to be playable at the same time --> I.e. multiple chat rooms. The way I tried to implement this did not work.
My question is: How is this generally done? Do people assign a different socket for each room? Or is there some other way of separating group of people 1 from group of people 2? I don't require code, I have more fun making my own when I know the general idea. So anything would help: A tutorial, or maybe a couple of sentences like "try this, try that".
Thanks guys!
Heinzel
I have written a multiplayer online game that includes a chat. The backend is a PHP script on the server. Players are connected to the game via PHP sockets. The game contains a chat, which I am mentioning because it is the best-known application for this sort of stuff. It all runs stable as long as there is only one group of people playing. But I want several games to be playable at the same time --> I.e. multiple chat rooms. The way I tried to implement this did not work.
My question is: How is this generally done? Do people assign a different socket for each room? Or is there some other way of separating group of people 1 from group of people 2? I don't require code, I have more fun making my own when I know the general idea. So anything would help: A tutorial, or maybe a couple of sentences like "try this, try that".
Thanks guys!
Heinzel
You can keep the same sockets, but the logic of differentiating people needs to be done server/client side. You need to transfer data between the client/server signifying which chat room they're sending the command in, and then the server interprets that, and makes sure to respond with the same information to let the client know which room the response came from.
IE:
User 1 is in Room A and B
User 2 is in Room A
User 3 is in Room B
User 1 types "Hello world" in A, Server responds by sending out "Hello world" to all clients in Room A
User 1 and User 2 see 1's "Hello world" message
User 3 says "Anyone there?" in B, Server responds by sending out "Anyone there?" to all clients in Room B
User 1 and User 3 see 3's "Anyone there?" message
It's all a matter of how you encode each command/response to deal with multiple rooms. You don't need multiple sockets for each user.
IE:
User 1 is in Room A and B
User 2 is in Room A
User 3 is in Room B
User 1 types "Hello world" in A, Server responds by sending out "Hello world" to all clients in Room A
User 1 and User 2 see 1's "Hello world" message
User 3 says "Anyone there?" in B, Server responds by sending out "Anyone there?" to all clients in Room B
User 1 and User 3 see 3's "Anyone there?" message
It's all a matter of how you encode each command/response to deal with multiple rooms. You don't need multiple sockets for each user.
- Ollie Saunders
- DevNet Master
- Posts: 3179
- Joined: Tue May 24, 2005 6:01 pm
- Location: UK
- superdezign
- DevNet Master
- Posts: 4135
- Joined: Sat Jan 20, 2007 11:06 pm
Run this from the command line:ole wrote:Puzzling. Could you should some code as to how you do this.Players are connected to the game via PHP sockets.
Code: Select all
<?php
$host = "127.0.0.1";
$port = 112233;
set_time_limit(0);
$sock = socket_create(AF_INET, SOCK_STREAM, 0);
socket_bind($sock, $host, $port);
socket_listen($sock, 3);
$child = socket_accept($sock);
socket_write($child, "Electric boogaloo!", strlen("Electric boogaloo!"));
socket_close($child);
socket_close($sock);
?>Thanks for the replies guys! First of all, as requested some code:
I hope this works as I cut out some 500 lines of code in between. For all that want to learn about PHP sockets, kirupa has a very good tutorial on Sockets with PHP 5 and Flash 8 at this location: http://www.kirupa.com/developer/flash8/ ... flash8.htm. Which answers the question of what my frontend is.
Code: Select all
#!/usr/bin/php -q
<?php
require_once ('database.php');
error_reporting(E_ALL);
set_time_limit(0);
ob_implicit_flush();
$address = gethostbyname('www.risk-online.net');
$port = 1240;
// Start Socket creation for PHP 5 Socket Server
if (($master = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) < 0) {
echo "socket_create() failed, reason: " . socket_strerror($master) . "\n";
}
socket_set_option($master, SOL_SOCKET,SO_REUSEADDR, 1);
if (($ret = socket_bind($master, $address, $port)) < 0) {
echo "socket_bind() failed, reason: " . socket_strerror($ret) . "\n";
}
if (($ret = socket_listen($master, 10)) < 0) {
echo "socket_listen() failed, reason: " . socket_strerror($ret) . "\n";
}
$read_sockets = array($master);
//Create Persistent Loop to continuously handle incoming socket messages
while (true) {
$changed_sockets = $read_sockets;
$num_changed_sockets = socket_select($changed_sockets, $write = NULL, $except = NULL, NULL);
foreach($changed_sockets as $socket) {
if ($socket == $master) {
if (($client = socket_accept($master)) < 0) {
echo "socket_accept() failed: reason: " . socket_strerror($msgsock) . "\n";
continue;
} else {
array_push($read_sockets, $client);
}
} else {
$bytes = socket_recv($socket, $buffer, 2048, 0);
if ($bytes == 0) {
$index = array_search($socket, $read_sockets);
unset($read_sockets[$index]);
socket_close($socket);
}else{
$allclients = $read_sockets;
array_shift($allclients);
$arguments = explode(",", $buffer);
if ($arguments[0] == "blabla") {
execute some command for blabla;
}
}
}
}
}
?>@ TheMoose: That is exactly how I attempted to do it. However, I don't seem to do it right. Please help me, you're the guy who apparently can! 
I basically try to assign the value of to a variable when someone signs in. The variable looks something like "Socket Ressource #8" (or any other number) when I print that out. I have an array, let's call it $room_a, and in $room_a I have several of those Socket Ressources stored. When I address them all, it works fine when there is only one room. But not once there are several... It mixes them up. Am I on the right track, I just didn't do it right somewhere along the way?
I will be gone to a festival this weekend ("Rock im Park" if anyone cares), so worry not if I won't reply before Monday. Please post anyway, I appreciate it a lot!
I basically try to assign the value of
Code: Select all
$allclients[count($allclients)-1]I will be gone to a festival this weekend ("Rock im Park" if anyone cares), so worry not if I won't reply before Monday. Please post anyway, I appreciate it a lot!
What you might want to try doing is have your clients send an additional argument for the room he/she is joining.
On the server, set up your connected clients array to be a bit different than what it is now. You'll need 2 arrays (ideally), one to store unlisted clients but connected clients, and another to store the clients associated to the room they're in. IE:
Pseudo:
When they first connect, you add them to the $master list. Once you read the room he/she is trying to join (it'd be better to have the client send a join command as well, instead of immediately a chat message), you remove them from the $master list, and add them to the appropriate $rooms listing.
Then whenever you receive a command, you look inside the associated $rooms list, and act upon that command to only the clients in that channel. It'll save you some processing time as you don't have to loop through an entire $master list of clients, instead you only loop through a smaller listing of clients in a given channel.
On the server, set up your connected clients array to be a bit different than what it is now. You'll need 2 arrays (ideally), one to store unlisted clients but connected clients, and another to store the clients associated to the room they're in. IE:
Pseudo:
Code: Select all
$rooms["A"][0] = $client1;
$rooms["A"][1] = $client2;
$rooms["B"][0] = $client3;
$rooms["B"][1] = $client1;
$master[0] = $client4; // hasn't read the bytes to determine what room he/she is in yetThen whenever you receive a command, you look inside the associated $rooms list, and act upon that command to only the clients in that channel. It'll save you some processing time as you don't have to loop through an entire $master list of clients, instead you only loop through a smaller listing of clients in a given channel.
@ TheMoose: Thanks, that's good stuff. I'll revamp the code after this weekend to the multidimensional array. Maybe as I redesign it, it'll get rid of whatever didn't work. I was just totally unsure how to approach multiple rooms as you can find applications easily, but never a tutorial or easily readable code for it on the web.
I'll post in here again sometime next week to keep you updated.
I'll post in here again sometime next week to keep you updated.