Jump to content

Recommended Posts

I have a very troubling problem at hand. I am using a web-socket server that runs in PHP. The issue is I need to be able to use a setInterval/setTimeout function similar to javascript, but within my php server.

 

I do not have the time or resources to convert my entire project over to nodejs/javascript. It will take forever. I love php so much, that I do not want to make the switch. Everything else works fine and I feel like it's not worth it to re-write everything just because I cannot use a similar setInterval function inside php.

 

Since the php socket server runs through the shell, I can use a setInterval type function using a loop:

 

protected function on_server_tick($counter)
{
    if($counter%5 == 0)
    {
        // 5 seconds interval
    }

    if($counter%10 == 0)
    {
        // 10 seconds interval
    }
}

$this->last_tick_time = microtime(true);
$this->tick_interval = 1;
$this->tick_counter = 0;

while(true)
{
    //loop code here...

    $t= microtime(true) - $this->last_tick_time;

    if($t>= $this->tick_interval)
    {
        $this->on_server_tick(++$this->tick_counter);
        $this->last_tick_time = microtime(true) - ($t- $this->tick_interval);
    }
}
 This code does work as intended, but it seems a bit overboard for resources and I feel like that while loop will suck a lot resources.

 

Is there anyway I can re-compile PHP from source and include a "while2" loop that only iterates every 500 miliseconds instead of instantly?

Edited by Dillybob

Please don't.

 

usleep.

$start = microtime(true);
while(true) {
    // stuff

    $end = microtime(true);
    $remaining = 0.5 - ($end - $start));
    if ($remaining > 0) usleep($remaining * 1e6);
    $start = $end;
}

Please don't.

 

usleep.

$start = microtime(true);
while(true) {
    // stuff

    $end = microtime(true);
    $remaining = 0.5 - ($end - $start));
    if ($remaining > 0) usleep($remaining * 1e6);
    $start = $end;
}

 

Thanks for the response.

One issue though. usleep won't work for my project as other players will be accessing that code at the same time (It will bottleneck other users access to the script itself)

 

Someone told me I need to use threads? Would that make the usleep per user specific? So it won't effect other people accessing the script?

Edited by Dillybob

Right, a server.

 

(Using forking terminology because that's easier to explain with:)

 

The server shouldn't be doing any actual work. It just spawns children and tracks ticks. I'd use two servers for that, actually, and a master daemon that creates and monitors those two.

  • Master daemon forks and monitors socket server process; if running in the background, the initial process forks and dies and the child becomes this master daemon
    • Socket server sets up listening socket and waits for children
    • Upon connection, server forks and monitors a child process for that connection
      • Child process communicates with the client
  • Master daemon forks and monitors tick server process
    • Tick server forks and monitors tick handler processes for each thing that has a tick action
      • Tick handlers sleep while they wait for a tick
      • When they wake, perform action, then go back to sleep
    • Tick server sleeps for ticks, wakes children (via socket or signal) when a tick happens
There's a socket pair between:

- Socket server and tick server

- Socket server and each client child

- Tick server and each handler child

 

Follow so far?

 

As for threads, if you can then that's better than forking processes. Overall scheme is still the same but the technical details, like forking and socket pairs, are different. Threads are also quite a bit different to manage so you should read up on threading and (presumably) PHP's pthreads before you start trying to add it to your code.

Edited by requinix

Don't mean to be rude but a lot of that stuff flew right over my head. (Not your fault)

 

From what I get is you're recommending a daemon server to be running along side my gameserver? And this can keep track of the setIntervals? (Or in this case, if I use PHP's pthreads) I can incorporate usleep, or your function above).

I'm actually going to add another process into the mix. With that in mind, here's what I was trying to describe:

 

- There is more than one process [1] running, each one having its own dedicated purpose

- Each client that connects gets its own process that is oriented towards supporting communication with the client

- There is a "socket server" that monitors each client process; it is the process that has the original socket that people connect to, but when they connect it creates a child to handle it rather than do the work by itself

- The socket server will often relay messages to and from a client process

- There is a process for each thing ("handler") that needs to run on ticks, and it can communicate with its managing process

- There is a "tick server" process that monitors each tick handler: it counts out the ticks and tells each child when a tick happens

- Likewise, the tick server will often relay messages to and from a tick handler

- (New) There is a "game server" process that deals with the game itself, and is what people would generally call "the server" when they're talking about this game

- The three server processes can communicate with each other

 

Here's an example of how it all works together. Let's take an MMO as an example:

- Game server starts and does whatever it needs to do (eg, initialize state, set up environments, whatever)

- Socket server starts and waits for connections

- Tick server starts and launches processes for all the tick handlers it has

- Tick handler #1: deals with the time of day, like it tracks when "day" and "night" happen:

1. When it starts it queries the game server for state and is told it is daytime - or is told the in-game time, or whatever

2. It runs, sleeps, runs, sleeps, and so on, waiting...

- Tick handler #2: resources regenerate 1 unit per 120 ticks (60s)

1. When it starts it sets a counter to 0

2. Every tick the counter increments

3. When the counter reaches 120 the process issues an update [2] and resets the counter to 0

- Now, a user connects:

1. They connect to the socket server

2. The socket server accepts the connection, spawns a child process for the client, and goes back to waiting for connections

3. The child process has the user authenticate and whatever, and informs the game server (via the socket server)

4. The game server sends information back about the client, blah blah blah

- As the user acts, the client processes sends information to the game server, which acts accordingly

- Meanwhile the tick handler has been executing, however it's currently daytime (as it was told by the game server) and nighttime hasn't come yet

- Eventually the tick handler detects a change to nighttime:

1. It sends a message to the game server (via the tick server) regarding the change

2. The game server updates itself

3. It then sends a "broadcast" message to the socket server to inform all clients of the change (by basically just passing the same message along to everyone)

- The user doesn't like playing during the dark and rage-quits:

1. The client process discovers the connection died

2. It passes a message to the game server (via the socket server) that the user disconnected

3. Game server updates accordingly

 

However as I explain this I realize I'm not a fan of ticks. Personally I would go for an event-based system since ticks can be simulated through sleeping:

- Daytime tick handler sleeps for however long day-/nighttime is, wakes, sends an event to update, and goes back to sleep

- Resources tick handler sleeps for a minute at a time

 

So questions for you:

1. Have more details about what this game (I presume) system is for and what it does?

2. What do you need ticks for?

 

And disclaimer: I know enough about socket programming and multi-threading/-processing to think I know what I'm talking about. You should also look for resources written by professionals.

 

[1] Again, because forking is easier to explain. The threading model is similar enough.

[2] Few possibilities. My first thought would be, essentially, executing an UPDATE query on a database, then informing the game server that resources have expired. This is slow. Faster would be having everything in memory, but I'm not knowledgeable enough to know how to pull that off well. (Shared memory, maybe?)

I'm actually going to add another process into the mix. With that in mind, here's what I was trying to describe:

 

- There is more than one process [1] running, each one having its own dedicated purpose

- Each client that connects gets its own process that is oriented towards supporting communication with the client

- There is a "socket server" that monitors each client process; it is the process that has the original socket that people connect to, but when they connect it creates a child to handle it rather than do the work by itself

- The socket server will often relay messages to and from a client process

- There is a process for each thing ("handler") that needs to run on ticks, and it can communicate with its managing process

- There is a "tick server" process that monitors each tick handler: it counts out the ticks and tells each child when a tick happens

- Likewise, the tick server will often relay messages to and from a tick handler

- (New) There is a "game server" process that deals with the game itself, and is what people would generally call "the server" when they're talking about this game

- The three server processes can communicate with each other

 

Here's an example of how it all works together. Let's take an MMO as an example:

- Game server starts and does whatever it needs to do (eg, initialize state, set up environments, whatever)

- Socket server starts and waits for connections

- Tick server starts and launches processes for all the tick handlers it has

- Tick handler #1: deals with the time of day, like it tracks when "day" and "night" happen:

1. When it starts it queries the game server for state and is told it is daytime - or is told the in-game time, or whatever

2. It runs, sleeps, runs, sleeps, and so on, waiting...

- Tick handler #2: resources regenerate 1 unit per 120 ticks (60s)

1. When it starts it sets a counter to 0

2. Every tick the counter increments

3. When the counter reaches 120 the process issues an update [2] and resets the counter to 0

- Now, a user connects:

1. They connect to the socket server

2. The socket server accepts the connection, spawns a child process for the client, and goes back to waiting for connections

3. The child process has the user authenticate and whatever, and informs the game server (via the socket server)

4. The game server sends information back about the client, blah blah blah

- As the user acts, the client processes sends information to the game server, which acts accordingly

- Meanwhile the tick handler has been executing, however it's currently daytime (as it was told by the game server) and nighttime hasn't come yet

- Eventually the tick handler detects a change to nighttime:

1. It sends a message to the game server (via the tick server) regarding the change

2. The game server updates itself

3. It then sends a "broadcast" message to the socket server to inform all clients of the change (by basically just passing the same message along to everyone)

- The user doesn't like playing during the dark and rage-quits:

1. The client process discovers the connection died

2. It passes a message to the game server (via the socket server) that the user disconnected

3. Game server updates accordingly

 

However as I explain this I realize I'm not a fan of ticks. Personally I would go for an event-based system since ticks can be simulated through sleeping:

- Daytime tick handler sleeps for however long day-/nighttime is, wakes, sends an event to update, and goes back to sleep

- Resources tick handler sleeps for a minute at a time

 

So questions for you:

1. Have more details about what this game (I presume) system is for and what it does?

2. What do you need ticks for?

 

And disclaimer: I know enough about socket programming and multi-threading/-processing to think I know what I'm talking about. You should also look for resources written by professionals.

 

[1] Again, because forking is easier to explain. The threading model is similar enough.

[2] Few possibilities. My first thought would be, essentially, executing an UPDATE query on a database, then informing the game server that resources have expired. This is slow. Faster would be having everything in memory, but I'm not knowledgeable enough to know how to pull that off well. (Shared memory, maybe?)

That is quite a reply. I understand the 'tick process' more thoroughly now though. Thanks for that!

 

My issue I'm trying to comprehend is, how in the hell do I install a tick server that runs along side with PHP? I'm currently re-writing my game socket server from php to nodejs (javascript), so I can literally, just use setInterval. I think it's a waste of time, but the setInterval is what will make the game dynamic and differentiate it between a regular pokemon combat game, or an action RPG where monsters can attack you. I'm aiming moreover for the dynamic attack system.

 

It's for monster ticks. As of right now, the only way a monster can do any damage to the main characters in game, is if a user engages a request to PHP so I can do the calculations. I am not going to rely on javascript clientside coding to cast the monster to attack, that is unreliable and not secure. This is where setInterval comes in and where I cannot achieve it with PHP.

 

When a player enters a world and walks in range to a monster the setInterval will start ticking. This will include the monsters attack speed, and other functions. This achieves a much more 'dynamic' and 'fluid' feel for combat and attack mechanisms. I can also incorporate HP Regeneration, MP Regeneration, fury regeneration and other fun stuff. All using simple setIntervals (or a simple ticker). That's pretty much the jist of it thus far.

Edited by Dillybob
This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.