amphp / websocket-client

Async WebSocket client for PHP based on Amp.

Home Page:https://amphp.org/websocket-client

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Are Ping Pong Control frames supported?

raghuveer opened this issue · comments

I am interested to know if amphp/websocket client responds with pong control frame to the ping control frame from web socket server, as per RFC6455 (https://tools.ietf.org/html/rfc6455#section-5.5)?

While this library is really helpful in sending web socket requests, in sync with amphp/redis library, in the scope of redis pubsub related subscribe method, the web socket connection is getting disconnected in few seconds after connection initiation (if I put websocket client connection code above and outside the while loop of amphp/redis library's subscribe method based code), even though my web socket server is configured to support Ping Pong Control frames.

I didnot use the While statement code of the amphp websocket client since, that blocks the next code (i.e. amphp/redis related channel subscription code), just to test, I did include amphp/websocket client connection code inside the While loop of amphp/redis related subscribe method, when the websocket connection is happening and connection is closing with the close command thereafter.

Is this approach scalable?

please share your thoughts to ensure, I be able to use websocket client connection code once, while using that connection code to send messages to the websocket server @kelunik

thank you

Yes, it does automatically respond to pings. Could you share your code that you think is blocked by the while loop?

The following is working code, if I put websocket client's connection inside while loop of amphp/redis related subscribe method

`\Amp\Loop::run(function() use ($channel){

$i = 0;

$subscription = yield $this->subscriber->subscribe($channel);
 
while (yield $subscription->advance()) {

	$subscriberResult = $subscription->getCurrent();
	
	$connection = yield connect('wss://ws-dev.postnub.com:8081');
	
	yield $connection->send($subscriberResult);
	yield $connection->close();
	
	if ($i < 3) {
		yield $connection->send("Ping: " . ++$i);
	} else {
		yield $connection->send("Goodbye!");
	}
	
}

});`

So you want to send all messages from the subscription to the websocket server?

Absolutely Yes, the goal is to have multiple websocket servers, and all user published messages will be received by one of the websocket servers, and the received messages will be posted to Redis pubsub, and the messages received through subscription code, will then be pushed to websocket server again using amphp websocket client and the following variations are tried and I have error situations, wherein, messages received from subscription code is not being sent to websocket server

scenario 1: websocket client related while loop is kept above amphp/redis subscription code

\Amp\Loop::run(function() use ($channel){

	$connection = yield connect('wss://ws-dev.postnub.com:8081');
	$i = 0;
	
	while ($message = yield $connection->receive()) {
        /** @var Message $message */
        $payload = yield $message->buffer();
        printf("Received: %s\n", $payload);

        if ($payload === "Goodbye!") {
            $connection->close();
            break;
        }

        yield delay(1000); // Pause the coroutine for 1 second.

        if ($i < 3) {
            yield $connection->send("Ping: " . ++$i);
        } else {
            yield $connection->send("Goodbye!");
        }
    }
	

	$subscription = yield $this->subscriber->subscribe($channel);
	 
	while (yield $subscription->advance()) {
	
		$subscriberResult = $subscription->getCurrent();
		
		$connection = yield connect('wss://ws-dev.postnub.com:8081');
		
		yield $connection->send($subscriberResult);
		yield $connection->close();
		
		if ($i < 3) {
			yield $connection->send("Ping: " . ++$i);
		} else {
			yield $connection->send("Goodbye!");
		}
		
	}

});

Scenario 2: Subscription code placed inside while loop of websocket client's while loop

\Amp\Loop::run(function() use ($channel){

	$connection = yield connect('wss://ws-dev.postnub.com:8081');
	$i = 0;
	
	while ($message = yield $connection->receive()) {
        /** @var Message $message */
        $payload = yield $message->buffer();
        printf("Received: %s\n", $payload);

        if ($payload === "Goodbye!") {
            $connection->close();
            break;
        }
		
		$subscription = yield $this->subscriber->subscribe($channel);
	 
		while (yield $subscription->advance()) {
		
			$subscriberResult = $subscription->getCurrent();
			
			$connection = yield connect('wss://ws-dev.postnub.com:8081');
			
			yield $connection->send($subscriberResult);
			yield $connection->close();
			
			if ($i < 3) {
				yield $connection->send("Ping: " . ++$i);
			} else {
				yield $connection->send("Goodbye!");
			}
			
		}

        yield delay(1000); // Pause the coroutine for 1 second.

        if ($i < 3) {
            yield $connection->send("Ping: " . ++$i);
        } else {
            yield $connection->send("Goodbye!");
        }
    }
});

scenario 3: had more issued when I used RatchetPawl websocket client before trying Amphp websocket client

@raghuveer Tip: Use three backticks + php and then a new line to format code, see Creating and highlighting code blocks.

The main problem seems to be that you don't know you can have multiple coroutines, not only the one created from the callable passed to Loop::run().

\Amp\Loop::run(function() use ($channel){
	$connection = yield connect('wss://ws-dev.postnub.com:8081');

    // Use Amp\call and handle errors if you want
    Amp\asyncCall(function () use ($connection) {
		while ($message = yield $connection->receive()) {
	         /** @var Message $message */
	         $payload = yield $message->buffer();
	         printf("Received: %s\n", $payload);
	  
	         if ($payload === "Goodbye!") {
	             $connection->close();
	             break;
	         }
	     }
	});
	
    Amp\asyncCall(function () use ($connection) {
		$i = 0;

		while (true) {
			yield delay(1000); // Pause the coroutine for 1 second.
	  
	        if ($i < 3) {
	            yield $connection->send("Ping: " . ++$i);
	        } else {
	            yield $connection->send("Goodbye!");
				break;
	        }
		}
	});

	$subscription = yield $this->subscriber->subscribe($channel);

	while (yield $subscription->advance()) {
		yield $connection->send($subscription->getCurrent());		
	}
});

I am new to using coroutines

Thanks a lot @kelunik for sharing the code sample,

will try this and share the update soon

UPDATE: The code is working flawlessly now.

hope this websocket connection, from amphp websocket client stays active irrespective of whether messages arrive in or not, like redis pubsub persistent connection know

Thanks a lot