mirror of https://github.com/grpc/grpc.io.git
448 lines
26 KiB
HTML
448 lines
26 KiB
HTML
|
|
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
|
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400" rel="stylesheet">
|
|
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
|
<title>
|
|
gRPC Basics - PHP – gRPC
|
|
</title>
|
|
|
|
|
|
<link rel="apple-touch-icon" href="/favicons/apple-touch-icon.png" sizes="180x180">
|
|
<link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192" >
|
|
<link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
|
|
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
|
<link rel="manifest" href="/favicons/manifest.json">
|
|
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#2DA6B0">
|
|
<meta name="msapplication-TileColor" content="#ffffff">
|
|
<meta name="msapplication-TileImage" content="/favicons/mstile-150x150.png">
|
|
|
|
|
|
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-60127042-1"></script>
|
|
<script>
|
|
window.dataLayer = window.dataLayer || [];
|
|
function gtag(){dataLayer.push(arguments);}
|
|
gtag('js', new Date());
|
|
|
|
gtag('config', 'UA-60127042-1');
|
|
</script>
|
|
|
|
</head>
|
|
<body>
|
|
<div id="landing-content">
|
|
<div class="row">
|
|
<div class="topbannersub">
|
|
<nav class="navbar navbar-expand-md navbar-dark topnav">
|
|
<a class="navbar-brand" href="https://cjyabraham.github.io/">
|
|
<img src="https://cjyabraham.github.io/img/grpc-logo.png" width="114" height="50">
|
|
</a>
|
|
|
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
|
<span class="navbar-toggler-icon"></span>
|
|
</button>
|
|
|
|
<div class="topnav, collapse navbar-collapse" id="navbarSupportedContent" style="float:right !important">
|
|
<ul class="navbar-nav ml-auto">
|
|
<li class="nav-item ">
|
|
<a class="nav-link" href="https://cjyabraham.github.io/about/">About</a>
|
|
</li>
|
|
<li class="nav-item dropdown active">
|
|
<a class="nav-link dropdown-toggle" href="https://cjyabraham.github.io/docs/" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
Docs
|
|
</a>
|
|
|
|
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
|
|
|
|
|
<a class="dropdown-item" href="/docs">
|
|
Overview
|
|
</a>
|
|
|
|
|
|
<a class="dropdown-item" href="/docs/quickstart/">
|
|
Quick Start
|
|
</a>
|
|
|
|
|
|
<a class="dropdown-item" href="/docs/guides/">
|
|
Guides
|
|
</a>
|
|
|
|
|
|
<a class="dropdown-item" href="/docs/tutorials/">
|
|
Tutorials
|
|
</a>
|
|
|
|
|
|
<a class="dropdown-item" href="/docs/reference/">
|
|
Reference
|
|
</a>
|
|
|
|
|
|
<a class="dropdown-item" href="/docs/samples/">
|
|
Samples
|
|
</a>
|
|
|
|
|
|
<a class="dropdown-item" href="/docs/talks">
|
|
Presentations
|
|
</a>
|
|
|
|
</div>
|
|
</li>
|
|
<li class="nav-item ">
|
|
<a class="nav-link" href="/blog">
|
|
Blog
|
|
</a>
|
|
</li>
|
|
<li class="nav-item ">
|
|
<a class="nav-link" href="/community">Community</a>
|
|
</li>
|
|
<li class="nav-item">
|
|
<a class="nav-link" href="https://packages.grpc.io/">
|
|
Packages
|
|
</a>
|
|
</li>
|
|
<li class="nav-item ">
|
|
<a class="nav-link" href="https://cjyabraham.github.io/faq/">FAQ</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</nav>
|
|
|
|
|
|
<div class="headertext">Documentation</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="subnav d-none d-md-block">
|
|
<a href="https://cjyabraham.github.io/docs/" >Overview</a>
|
|
| <a href="https://cjyabraham.github.io/docs/quickstart/" >Quick Start</a>
|
|
| <a href="https://cjyabraham.github.io/docs/guides/" >Guides</a>
|
|
| <a href="https://cjyabraham.github.io/docs/tutorials/" class="active">Tutorials</a>
|
|
| <a href="https://cjyabraham.github.io/docs/reference/" >Reference</a>
|
|
| <a href="https://cjyabraham.github.io/docs/samples/" >Samples</a>
|
|
| <a href="https://cjyabraham.github.io/docs/talks/" >Presentations</a>
|
|
</div>
|
|
|
|
|
|
<div class="quickstartcols">
|
|
|
|
<div class="quickstartcol1">
|
|
|
|
<h8>Tutorials</h8>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/async/helloasync-cpp/" >Async - C++</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/auth/oauth2-objective-c/" >Auth - Objective C</a>
|
|
<h8>Basic</h8>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/c/" >C++</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/csharp/" >C#</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/dart/" >Dart</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/go/" >Go</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/java/" >Java</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/android/" >Android Java</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/node/" >Node</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/objective-c/" >Objective-C</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/php/" class="active">PHP</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/python/" >Python</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/ruby/" >Ruby</a>
|
|
<a href="https://cjyabraham.github.io/docs/tutorials/basic/web/" >Web</a>
|
|
|
|
</div>
|
|
|
|
<div class="quickstartcol2" style="margin-top:4%">
|
|
<h3 style="margin-top:0px;">gRPC Basics - PHP</h3>
|
|
|
|
|
|
|
|
<p>This tutorial provides a basic PHP programmer’s introduction to
|
|
working with gRPC.</p>
|
|
|
|
<p>By walking through this example you’ll learn how to:</p>
|
|
|
|
<ul>
|
|
<li>Define a service in a .proto file.</li>
|
|
<li>Generate client code using the protocol buffer compiler.</li>
|
|
<li>Use the PHP gRPC API to write a simple client for your service.</li>
|
|
</ul>
|
|
|
|
<p>It assumes a passing familiarity with <a href="https://developers.google.com/protocol-buffers/docs/overview">protocol
|
|
buffers</a>. Note
|
|
that the example in this tutorial uses the proto2 version of the protocol
|
|
buffers language.</p>
|
|
|
|
<p>Also note that currently you can only create clients in PHP for gRPC services -
|
|
you can find out how to create gRPC servers in our other tutorials, e.g.
|
|
<a href="/docs/tutorials/basic/node/">Node.js</a>.</p>
|
|
|
|
<div id="toc"></div>
|
|
|
|
<p><a name="why-grpc"></a></p>
|
|
|
|
<h3 id="why-use-grpc">Why use gRPC?</h3>
|
|
|
|
<p>With gRPC you can define your service once in a .proto file and implement
|
|
clients and servers in any of gRPC’s supported languages, which in turn can be
|
|
run in environments ranging from servers inside Google to your own tablet - all
|
|
the complexity of communication between different languages and environments is
|
|
handled for you by gRPC. You also get all the advantages of working with
|
|
protocol buffers, including efficient serialization, a simple IDL, and easy
|
|
interface updating.</p>
|
|
|
|
<p><a name="setup"></a></p>
|
|
|
|
<h3 id="example-code-and-setup">Example code and setup</h3>
|
|
|
|
<p>The example code for our tutorial is in
|
|
<a href="https://github.com/grpc/grpc/tree/v1.20.0/examples/php/route_guide">grpc/grpc/examples/php/route_guide</a>.
|
|
To download the example, clone the <code>grpc</code> repository by running the following
|
|
command:</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ git clone -b v1.20.0 https://github.com/grpc/grpc</code></pre></div>
|
|
<p>You need grpc-php-plugin to help you generate proto files. You can build it from source:</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ cd grpc <span style="color:#f92672">&&</span> git submodule update --init <span style="color:#f92672">&&</span> make grpc_php_plugin</code></pre></div>
|
|
<p>Then change your current directory to <code>examples/php/route_guide</code> and generate proto files:</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ cd examples/php/route_guide
|
|
$ ./route_guide_proto_gen.sh</code></pre></div>
|
|
<p>Our example is a simple route mapping application that lets clients get
|
|
information about features on their route, create a summary of their route, and
|
|
exchange route information such as traffic updates with the server and other
|
|
clients.</p>
|
|
|
|
<p>You also should have the relevant tools installed to generate the client
|
|
interface code (and a server in another language, for testing). You can obtain
|
|
the latter by following <a href="/docs/tutorials/basic/node/">these setup
|
|
instructions</a>.</p>
|
|
|
|
<p><a name="try"></a></p>
|
|
|
|
<h3 id="try-it-out">Try it out!</h3>
|
|
|
|
<p>To try the sample app, we need a gRPC server running locally. Let’s compile and
|
|
run, for example, the Node.js server in this repository:</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ cd ../../node
|
|
$ npm install
|
|
$ cd dynamic_codegen/route_guide
|
|
$ nodejs ./route_guide_server.js --db_path<span style="color:#f92672">=</span>route_guide_db.json</code></pre></div>
|
|
<p>Run the PHP client (in a different terminal):</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ ./run_route_guide_client.sh</code></pre></div>
|
|
<p>The next sections guide you step-by-step through how this proto service is
|
|
defined, how to generate a client library from it, and how to create a client
|
|
stub that uses that library.</p>
|
|
|
|
<p><a name="proto"></a></p>
|
|
|
|
<h3 id="defining-the-service">Defining the service</h3>
|
|
|
|
<p>First let’s look at how the service we’re using is defined. A gRPC <em>service</em> and
|
|
its method <em>request</em> and <em>response</em> types using <a href="https://developers.google.com/protocol-buffers/docs/overview">protocol
|
|
buffers</a>. You can
|
|
see the complete .proto file for our example in
|
|
<a href="https://github.com/grpc/grpc/blob/v1.20.0/examples/protos/route_guide.proto"><code>examples/protos/route_guide.proto</code></a>.</p>
|
|
|
|
<p>To define a service, you specify a named <code>service</code> in your .proto file:</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-protobuf" data-lang="protobuf"><span style="color:#66d9ef">service</span> RouteGuide {<span style="color:#960050;background-color:#1e0010">
|
|
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#f92672">...</span><span style="color:#960050;background-color:#1e0010">
|
|
</span><span style="color:#960050;background-color:#1e0010"></span>}</code></pre></div>
|
|
<p>Then you define <code>rpc</code> methods inside your service definition, specifying their
|
|
request and response types. Protocol buffers let you define four kinds of
|
|
service method, all of which are used in the <code>RouteGuide</code> service:</p>
|
|
|
|
<ul>
|
|
<li>A <em>simple RPC</em> where the client sends a request to the server and receives a
|
|
response later, just like a normal remote procedure call.</li>
|
|
</ul>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-protobuf" data-lang="protobuf"><span style="color:#75715e">// Obtains the feature at a given position.
|
|
</span><span style="color:#75715e"></span><span style="color:#66d9ef">rpc</span> GetFeature(Point) <span style="color:#66d9ef">returns</span> (Feature) {}</code></pre></div>
|
|
<ul>
|
|
<li>A <em>response-streaming RPC</em> where the client sends a request to the server and
|
|
gets back a stream of response messages. You specify a response-streaming
|
|
method by placing the <code>stream</code> keyword before the <em>response</em> type.</li>
|
|
</ul>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-protobuf" data-lang="protobuf"><span style="color:#75715e">// Obtains the Features available within the given Rectangle. Results are
|
|
</span><span style="color:#75715e">// streamed rather than returned at once (e.g. in a response message with a
|
|
</span><span style="color:#75715e">// repeated field), as the rectangle may cover a large area and contain a
|
|
</span><span style="color:#75715e">// huge number of features.
|
|
</span><span style="color:#75715e"></span><span style="color:#66d9ef">rpc</span> ListFeatures(Rectangle) <span style="color:#66d9ef">returns</span> (stream Feature) {}</code></pre></div>
|
|
<ul>
|
|
<li>A <em>request-streaming RPC</em> where the client sends a sequence of messages to the
|
|
server. Once the client has finished writing the messages, it waits for the
|
|
server to read them all and return its response. You specify a
|
|
request-streaming method by placing the <code>stream</code> keyword before the <em>request</em>
|
|
type.</li>
|
|
</ul>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-protobuf" data-lang="protobuf"><span style="color:#75715e">// Accepts a stream of Points on a route being traversed, returning a
|
|
</span><span style="color:#75715e">// RouteSummary when traversal is completed.
|
|
</span><span style="color:#75715e"></span><span style="color:#66d9ef">rpc</span> RecordRoute(stream Point) <span style="color:#66d9ef">returns</span> (RouteSummary) {}</code></pre></div>
|
|
<ul>
|
|
<li>A <em>bidirectional streaming RPC</em> where both sides send a sequence of messages
|
|
to the other. The two streams operate independently, so clients and servers
|
|
can read and write in whatever order they like: for example, the server could
|
|
wait to receive all the client messages before writing its responses, or it
|
|
could alternately read a message then write a message, or some other
|
|
combination of reads and writes. The order of messages in each stream is
|
|
preserved. You specify this type of method by placing the <code>stream</code> keyword
|
|
before both the request and the response.</li>
|
|
</ul>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-protobuf" data-lang="protobuf"><span style="color:#75715e">// Accepts a stream of RouteNotes sent while a route is being traversed,
|
|
</span><span style="color:#75715e">// while receiving other RouteNotes (e.g. from other users).
|
|
</span><span style="color:#75715e"></span><span style="color:#66d9ef">rpc</span> RouteChat(stream RouteNote) <span style="color:#66d9ef">returns</span> (stream RouteNote) {}</code></pre></div>
|
|
<p>Our .proto file also contains protocol buffer message type definitions for all
|
|
the request and response types used in our service methods - for example, here’s
|
|
the <code>Point</code> message type:</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-protobuf" data-lang="protobuf"><span style="color:#75715e">// Points are represented as latitude-longitude pairs in the E7 representation
|
|
</span><span style="color:#75715e">// (degrees multiplied by 10**7 and rounded to the nearest integer).
|
|
</span><span style="color:#75715e">// Latitudes should be in the range +/- 90 degrees and longitude should be in
|
|
</span><span style="color:#75715e">// the range +/- 180 degrees (inclusive).
|
|
</span><span style="color:#75715e"></span><span style="color:#66d9ef">message</span> <span style="color:#a6e22e">Point</span> {<span style="color:#960050;background-color:#1e0010">
|
|
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">int32</span> latitude <span style="color:#f92672">=</span> <span style="color:#ae81ff">1</span>;<span style="color:#960050;background-color:#1e0010">
|
|
</span><span style="color:#960050;background-color:#1e0010"></span> <span style="color:#66d9ef">int32</span> longitude <span style="color:#f92672">=</span> <span style="color:#ae81ff">2</span>;<span style="color:#960050;background-color:#1e0010">
|
|
</span><span style="color:#960050;background-color:#1e0010"></span>}</code></pre></div>
|
|
<p><a name="protoc"></a></p>
|
|
|
|
<h3 id="generating-client-code">Generating client code</h3>
|
|
|
|
<p>The PHP client stub implementation of the proto files can be generated by the
|
|
gRPC PHP Protoc Plugin. To compile the plugin:</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ make grpc_php_plugin</code></pre></div>
|
|
<p>To generate the client stub implementation .php file:</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ cd grpc
|
|
$ protoc --proto_path<span style="color:#f92672">=</span>examples/protos <span style="color:#ae81ff">\
|
|
</span><span style="color:#ae81ff"></span> --php_out<span style="color:#f92672">=</span>examples/php/route_guide <span style="color:#ae81ff">\
|
|
</span><span style="color:#ae81ff"></span> --grpc_out<span style="color:#f92672">=</span>examples/php/route_guide <span style="color:#ae81ff">\
|
|
</span><span style="color:#ae81ff"></span> --plugin<span style="color:#f92672">=</span>protoc-gen-grpc<span style="color:#f92672">=</span>bins/opt/grpc_php_plugin <span style="color:#ae81ff">\
|
|
</span><span style="color:#ae81ff"></span> ./examples/protos/route_guide.proto</code></pre></div>
|
|
<p>or running the helper script under the <code>grpc/example/php/route_guide</code> directory if you build
|
|
grpc-php-plugin by source:</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-sh" data-lang="sh">$ ./route_guide_proto_gen.sh</code></pre></div>
|
|
<p>A number of files will be generated in the <code>examples/php/route_guide</code> directory.
|
|
You do not need to modify those files.</p>
|
|
|
|
<p>To load these generated files, add this section to your <code>composer.json</code> file under
|
|
<code>examples/php</code> directory</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-json" data-lang="json"> <span style="color:#e6db74">"autoload"</span><span style="color:#960050;background-color:#1e0010">:</span> {
|
|
<span style="color:#f92672">"psr-4"</span>: {
|
|
<span style="color:#f92672">""</span>: <span style="color:#e6db74">"route_guide/"</span>
|
|
}
|
|
}</code></pre></div>
|
|
<p>The file contains:</p>
|
|
|
|
<ul>
|
|
<li>All the protocol buffer code to populate, serialize, and retrieve our request
|
|
and response message types.</li>
|
|
<li>A class called <code>Routeguide\RouteGuideClient</code> that lets clients call the methods
|
|
defined in the <code>RouteGuide</code> service.</li>
|
|
</ul>
|
|
|
|
<p><a name="client"></a></p>
|
|
|
|
<h3 id="creating-the-client">Creating the client</h3>
|
|
|
|
<p>In this section, we’ll look at creating a PHP client for our <code>RouteGuide</code>
|
|
service. You can see our complete example client code in
|
|
<a href="https://github.com/grpc/grpc/blob/v1.20.0/examples/php/route_guide/route_guide_client.php">examples/php/route_guide/route_guide_client.php</a>.</p>
|
|
|
|
<h4 id="constructing-a-client-object">Constructing a client object</h4>
|
|
|
|
<p>To call service methods, we first need to create a client object, an instance of
|
|
the generated <code>RouteGuideClient</code> class. The constructor of the class expects the
|
|
server address and port we want to connect to:</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php">$client = new Routeguide\RouteGuideClient('localhost:50051', [
|
|
'credentials' => Grpc\ChannelCredentials::createInsecure(),
|
|
]);</code></pre></div>
|
|
<h4 id="calling-service-methods">Calling service methods</h4>
|
|
|
|
<p>Now let’s look at how we call our service methods.</p>
|
|
|
|
<h5 id="simple-rpc">Simple RPC</h5>
|
|
|
|
<p>Calling the simple RPC <code>GetFeature</code> is nearly as straightforward as calling a
|
|
local asynchronous method.</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php">$point = new Routeguide\Point();
|
|
$point->setLatitude(409146138);
|
|
$point->setLongitude(-746188906);
|
|
list($feature, $status) = $client->GetFeature($point)->wait();</code></pre></div>
|
|
<p>As you can see, we create and populate a request object, i.e. an
|
|
<code>Routeguide\Point</code> object. Then, we call the method on the stub, passing it the
|
|
request object. If there is no error, then we can read the response information
|
|
from the server from our response object, i.e. an <code>Routeguide\Feature</code> object.</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php">print sprintf("Found %s \n at %f, %f\n", $feature->getName(),
|
|
$feature->getLocation()->getLatitude() / COORD_FACTOR,
|
|
$feature->getLocation()->getLongitude() / COORD_FACTOR);</code></pre></div>
|
|
<h5 id="streaming-rpcs">Streaming RPCs</h5>
|
|
|
|
<p>Now let’s look at our streaming methods. Here’s where we call the server-side
|
|
streaming method <code>ListFeatures</code>, which returns a stream of geographical
|
|
<code>Feature</code>s:</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php">$lo_point = new Routeguide\Point();
|
|
$hi_point = new Routeguide\Point();
|
|
|
|
$lo_point->setLatitude(400000000);
|
|
$lo_point->setLongitude(-750000000);
|
|
$hi_point->setLatitude(420000000);
|
|
$hi_point->setLongitude(-730000000);
|
|
|
|
$rectangle = new Routeguide\Rectangle();
|
|
$rectangle->setLo($lo_point);
|
|
$rectangle->setHi($hi_point);
|
|
|
|
$call = $client->ListFeatures($rectangle);
|
|
// an iterator over the server streaming responses
|
|
$features = $call->responses();
|
|
foreach ($features as $feature) {
|
|
// process each feature
|
|
} // the loop will end when the server indicates there is no more responses to be sent.</code></pre></div>
|
|
<p>The <code>$call->responses()</code> method call returns an iterator. When the server sends
|
|
a response, a <code>$feature</code> object will be returned in the <code>foreach</code> loop, until
|
|
the server indiciates that there will be no more responses to be sent.</p>
|
|
|
|
<p>The client-side streaming method <code>RecordRoute</code> is similar, except that we call
|
|
<code>$call->write($point)</code> for each point we want to write from the client side and
|
|
get back a <code>Routeguide\RouteSummary</code>.</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php">$call = $client->RecordRoute();
|
|
|
|
for ($i = 0; $i <span style="color:#960050;background-color:#1e0010"><</span> $num_points; $i++) {
|
|
$point = new Routeguide\Point();
|
|
$point->setLatitude($lat);
|
|
$point->setLongitude($long);
|
|
$call->write($point);
|
|
}
|
|
|
|
list($route_summary, $status) = $call->wait();</code></pre></div>
|
|
<p>Finally, let’s look at our bidirectional streaming RPC <code>routeChat()</code>. In this
|
|
case, we just pass a context to the method and get back a <code>BidiStreamingCall</code>
|
|
stream object, which we can use to both write and read messages.</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php">$call = $client->RouteChat();</code></pre></div>
|
|
<p>To write messages from the client:</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php">foreach ($notes as $n) {
|
|
$route_note = new Routeguide\RouteNote();
|
|
$call->write($route_note);
|
|
}
|
|
$call->writesDone();</code></pre></div>
|
|
<p>To read messages from the server:</p>
|
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-php" data-lang="php">while ($route_note_reply = $call->read()) {
|
|
// process $route_note_reply
|
|
}</code></pre></div>
|
|
<p>Each side will always get the other’s messages in the order they were written,
|
|
both the client and server can read and write in any order — the streams operate
|
|
completely independently.</p>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
|
|
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
|
|
|
|
</body>
|
|
</html>
|