Viewed   163 times

I am using web socket using PHP5 and the Chrome browser as client. I have taken the code from the site http://code.google.com/p/phpwebsocket/.

I run the server, and the client is also connected. I can chat as well. Now when I restart the server (by killing it and starting it again), the client gets the disconnected information, but automatically doesn't reconnect with server when I send the message.

How to achieve this? Like when I get the dis-connected information, should I check it and send it to JavaScript to refresh the page or reconnect?

 Answers

1

When the server reboots, the Web Socket connection is closed, so the JavaScript onclose event is triggered. Here's an example that tries to reconnect every five seconds.

function start(websocketServerLocation){
    ws = new WebSocket(websocketServerLocation);
    ws.onmessage = function(evt) { alert('message received'); };
    ws.onclose = function(){
        // Try to reconnect in 5 seconds
        setTimeout(function(){start(websocketServerLocation)}, 5000);
    };
}
Saturday, August 6, 2022
5

This is tricky.

You need to execute the server.php script and it needs to never exit. If you have an SSH access to your shared server, you could execute it just like they do on the screenshot and make it run as a background task using something like nohup:

$ nohup php server.php
nohup: ignoring input and appending output to `nohup.out'

After invoking this (using the SSH connection), you may exit and the process will continue running. Everything the script prints will be stored into nohup.out, which you can read at any time.

If you don't have an SSH access, and the only way to actually execute a PHP script is through Apache as the result of a page request, then you could simply go to that page using a browser and never close the browser. But there will be a time out one day or another and the connection between you and Apache will close, effectively stopping the server.php script execution.

And in those previous cases, a lot of shared hosts will not permit a script to run indefinitely. You will notice that there's this line in server.php:

set_time_limit(0);

This tells PHP that there's no time limit. If the host made PHP run in safe mode (which a lot of them do), then you cannot use set_time_limit and the time limit is probably 30 seconds or even less.

So yes, a VPS is probably your best bet. Now, I don't own one myself, and I don't know what's a good/bad price, but I'd say HostGator seems fine.

Sunday, November 20, 2022
 
5

My bet is that your host is blocking incoming requests to the socket. Your not supposed to run scripts like phpwebsocket within a web service (it is a server itself). This confuses a lot of people since PHP is typically used for scripting webpages, not for coding daemons.

I say this because you mentioned running the script within Xampp, and referred to your hosting service as 'webspace'.

If this is the case you will have to upgrade to a virtual server package so that you can run your own services.

Monday, October 17, 2022
 
4

This is a least squares problem with 100,000 responses. Your bigmatrix is the response (matrix), beta is the coefficient (matrix), while w1 is the residual (matrix).

bigmatrix, as well as w1, if formed explicitly, will each cost

(100,000 * 100,000 * 8) / (1024 ^ 3) = 74.5 GB

This is far too large.

As estimation for each response is independent, there is really no need to form bigmatrix in one go and try to store it in RAM. We can just form it tile by tile, and use an iterative procedure: form a tile, use a tile, then discard it. For example, the below considers a tile of dimension 100,000 * 2,000, with memory size:

(100,000 * 2,000 * 8) / (1024 ^ 3) = 1.5 GB

By such iterative procedure, the memory usage is effectively under control.

x1 <- rnorm(100000)
x2 <- rnorm(100000)
g <- cbind(x1, x2, x1^2, x2^2)
gg <- crossprod(g)    ## don't use `t(g) %*% g`
## we also don't explicitly form `gg` inverse

## initialize `beta` matrix (4 coefficients for each of 100,000 responses)
beta <- matrix(0, 4, 100000)

## we split 100,000 columns into 50 tiles, each with 2000 columns
for (i in 1:50) {
   start <- 2000 * (i-1) + 1    ## chunk start
   end <- 2000 * i    ## chunk end
   bigmatrix <- outer(x1, x2[start:end], "<=")
   Gw <- crossprod(g, bigmatrix)    ## don't use `t(g) %*% bigmatrix`
   beta[, start:end] <- solve(gg, Gw)
   }

Note, don't try to compute the residual matrix w1, as It will cost 74.5 GB. If you need residual matrix in later work, you should still try to break it into tiles and work one by one.

You don't need to worry about the loop here. The computation inside each iteration is costly enough to amortize looping overhead.

Wednesday, August 31, 2022
 
p4plus2
 
2

Don't worry.

Your code is running within a single threaded event loop.

This line: var sock = new WebSocket(url); doesn't initiate a websocket connection at all. The spec says that it must perform the actual connection only after returning the web socket, in parallel with the thread handling the event loop your code is running on:

  1. Return a new WebSocket object, but continue these steps [in parallel][2].

That alone wouldn't be sufficient, but all subsequent WebSocket events for that socket are scheduled inside the same single-threaded event loop that is running your code. Here's what the spec says about receiving a message:

When a WebSocket message has been received with type type and data data, the user agent must queue a task to follow these steps

That task is queued on the same event loop. That means that the task to process the message cannot be run until the task where you created your WebSocket has run to completion. So your code will finish running before the event loop will process any connection related messages.

Even if you're running your code in a browser that uses many threads, the specific code will run on a single threaded event loop and each event loop will be independent.

Different event loops can and do communicate by pushing tasks into each other's task-queues. But these tasks will be executed within the single-threaded event-loop that received the task, keeping your code thread-safe.

The task "handle this event" will be handled by the single threaded event loop finding the appropriate event handler and calling its callback... but this will only happen once the task is already being handled.

To be clearer:

I'm not claiming that each event-loop actually handles the IO - but the IO scheduler will send your code events and these events will run sequentially within a single thread (sort of, they do have priority management that uses different "task queues").

EDIT: client code concerns

It should be noted that the Websocket API wasn't designed for the DOM's function addEventListener.

Instead, the Websocket API follows the HTML4 paradigm, where event callbacks are object properties (rather than the EventListener collection). i.e.:

// altered DOM API:
sock.addEventListener('message', processMessage);
// original WebSocket API:
sock.onmessage = processMessage;

Both APIs work correctly on all the browsers I tested (including safe delivery of first message). The difference in approaches is probably handled by the HTML4 compatibility layer.

However the specification regarding event scheduling is different, so the use of addEventListener should probably be avoided.

EDIT 2 : Testing the Theory

Regarding Bronze Man's answer concerning failed message responses...

I couldn't reproduce the claimed issue, even though I wrote a test using a small Ruby application and a small Javascript Client.

The Ruby application starts up a Websocket echo server with a welcome message (I'm using plezi.io).

The Javascript client contains a busy-wait loop that causes the Javascript thread to hang (block) for the specified amount of time (2 seconds in my tests).

The onmessage callback is set only after the block is released (after 2 seconds) - so the welcome message from the server will arrive at the browser before the callback is defined.

This allows us to test if the welcome message is lost on any specific browser (which would be a bug in the browser).

The test is reliable since the server is a known quantity and will send the message to the socket as soon as the upgrade is complete (I wrote the Iodine server backend in C as well as the plezi.io framework and I chose them because of my deep knowledge of their internal behavior).

The Ruby application:

# run from terminal using `irb`, after `gem install plezi`
require 'plezi'
class WebsocketEcho
    def index
       "Use Websockets"
    end
    def on_message data
       # simple echo
       write data
    end
    def on_open
       # write a welcome message
       # will ths message be lost?
       write "Welcome to the WebSocket echo server."
       puts "New Websocket connection opened, welcome message was sent."
    end
end
# adds mixins to the class and creates route
Plezi.route("/", WebsocketEcho)

# running the server from the terminal
Iodine.threads = 1
Iodine::Rack.app = Plezi.app
Iodine.start

The Javascript Client:

function Client(milli) {
    this.ws = new WebSocket("ws" + window.document.location.href.slice(4, -1));
    this.ws.client = this;
    this.onopen = function (e) { console.log("Websocket opened", e); }
    this.ws.onopen = function (e) { e.target.client.onopen(e); }
    this.onclose = function (e) { console.log("Websocket closed", e); /* reconnect? */ }
    this.ws.onclose = function (e) { e.target.client.onclose(e); }
    if(milli) { // busy wait, blocking the thread.
        var start = new Date();
        var now = null;
        do {
            now = new Date();
        } while(now - start < milli);
    }
    this.onmessage = function (e) { console.log(e.data); }
    // // DOM API alternative for testing:
    // this.ws.addEventListener('message', function (e) { e.target.client.onmessage(e); });
    // // WebSocket API for testing:
    this.ws.onmessage = function (e) { e.target.client.onmessage(e); }    
}
// a 2 second window
cl = new Client(2000);

Results on my machine (MacOS):

  • Safari 11.01 initiates the Websocket connection only after the new client was creation is complete (after the thread is done processing the code, as indicated by the Ruby application's delayed output). The message obviously arrived once the connection was made.

  • Chrome 62.0 initiates the Websocket connection immediately. The message arrives once the 2 second window ends. Message wasn't lost even though it arrived before the onmessage handler was set.

  • FireFox 56.0 behaves the same as Chrome, initiating the Websocket connection immediately. The message arrives once the 2 second window ends. Message wasn't lost.

If someone could test on Windows and Linux, that would be great... but I don't think the browsers will have implementation issues with the event scheduling. I believe the specifications can be trusted.

Saturday, December 10, 2022
 
tordek
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :