mirror of https://github.com/grpc/grpc.git
commit
9e6e57bfba
850 changed files with 31780 additions and 22294 deletions
@ -0,0 +1,59 @@ |
||||
# Configuration for probot-stale - https://github.com/probot/stale |
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request becomes stale |
||||
daysUntilStale: 180 |
||||
|
||||
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed. |
||||
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. |
||||
daysUntilClose: 1 |
||||
|
||||
# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled) |
||||
onlyLabels: [] |
||||
|
||||
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable |
||||
exemptLabels: |
||||
- "disposition/never stale" |
||||
|
||||
# Set to true to ignore issues in a project (defaults to false) |
||||
exemptProjects: false |
||||
|
||||
# Set to true to ignore issues in a milestone (defaults to false) |
||||
exemptMilestones: false |
||||
|
||||
# Set to true to ignore issues with an assignee (defaults to false) |
||||
exemptAssignees: false |
||||
|
||||
# Label to use when marking as stale |
||||
staleLabel: "disposition/stale" |
||||
|
||||
# Comment to post when marking as stale. Set to `false` to disable |
||||
markComment: > |
||||
This issue/PR has been automatically marked as stale because it has not had any update (including |
||||
commits, comments, labels, milestones, etc) for 180 days. It will be closed automatically if no |
||||
further update occurs in 1 day. Thank you for your contributions! |
||||
|
||||
# Comment to post when removing the stale label. |
||||
# unmarkComment: > |
||||
# Your comment here. |
||||
|
||||
# Comment to post when closing a stale Issue or Pull Request. |
||||
# closeComment: > |
||||
# Your comment here. |
||||
|
||||
# Limit the number of actions per hour, from 1-30. Default is 30 |
||||
limitPerRun: 30 |
||||
|
||||
# Limit to only `issues` or `pulls` |
||||
# only: issues |
||||
|
||||
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls': |
||||
# pulls: |
||||
# daysUntilStale: 30 |
||||
# markComment: > |
||||
# This pull request has been automatically marked as stale because it has not had |
||||
# recent activity. It will be closed if no further activity occurs. Thank you |
||||
# for your contributions. |
||||
|
||||
# issues: |
||||
# exemptLabels: |
||||
# - confirmed |
@ -1,3 +1,4 @@ |
||||
Dropbox, Inc. |
||||
Google Inc. |
||||
Skyscanner Ltd. |
||||
WeWork Companies Inc. |
||||
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1 @@ |
||||
This repository is governed by the gRPC organization's [governance rules](https://github.com/grpc/grpc-community/blob/master/governance.md). |
@ -0,0 +1,82 @@ |
||||
This page lists all active maintainers of this repository. If you were a |
||||
maintainer and would like to add your name to the Emeritus list, please send us a |
||||
PR. |
||||
|
||||
See [GOVERNANCE.md](https://github.com/grpc/grpc-community/blob/master/governance.md) |
||||
for governance guidelines and how to become a maintainer. |
||||
See [CONTRIBUTING.md](https://github.com/grpc/grpc-community/blob/master/CONTRIBUTING.md) |
||||
for general contribution guidelines. |
||||
|
||||
## Maintainers (in alphabetical order) |
||||
- [a11r](https://github.com/a11r), Google LLC |
||||
- [apolcyn](https://github.com/apolcyn), Google LLC |
||||
- [arjunroy](https://github.com/arjunroy), Google LLC |
||||
- [AspirinSJL](https://github.com/AspirinSJL), Google LLC |
||||
- [bogdandrutu](https://github.com/bogdandrutu), Google LLC |
||||
- [daniel-j-born](https://github.com/daniel-j-born), Google LLC |
||||
- [dapengzhang0](https://github.com/dapengzhang0), Google LLC |
||||
- [dfawley](https://github.com/dfawley), Google LLC |
||||
- [dklempner](https://github.com/dklempner), Google LLC |
||||
- [ejona86](https://github.com/ejona86), Google LLC |
||||
- [gnossen](https://github.com/gnossen), Google LLC |
||||
- [guantaol](https://github.com/guantaol), Google LLC |
||||
- [hcaseyal](https://github.com/hcaseyal), Google LLC |
||||
- [jboeuf](https://github.com/jboeuf), Google LLC |
||||
- [jiangtaoli2016](https://github.com/jiangtaoli2016), Google LLC |
||||
- [jkolhe](https://github.com/jkolhe), Google LLC |
||||
- [jtattermusch](https://github.com/jtattermusch), Google LLC |
||||
- [karthikravis](https://github.com/karthikravis), Google LLC |
||||
- [kumaralokgithub](https://github.com/kumaralokgithub), Google LLC |
||||
- [lidizheng](https://github.com/lidizheng), Google LLC |
||||
- [markdroth](https://github.com/markdroth), Google LLC |
||||
- [matthewstevenson88](https://github.com/matthewstevenson88), Google LLC |
||||
- [mehrdada](https://github.com/mehrdada), Dropbox, Inc. |
||||
- [mhaidrygoog](https://github.com/mhaidrygoog), Google LLC |
||||
- [murgatroid99](https://github.com/murgatroid99), Google LLC |
||||
- [muxi](https://github.com/muxi), Google LLC |
||||
- [nanahpang](https://github.com/nanahpang), Google LLC |
||||
- [nathanielmanistaatgoogle](https://github.com/nathanielmanistaatgoogle), Google LLC |
||||
- [nicolasnoble](https://github.com/nicolasnoble), Google LLC |
||||
- [qixuanl1](https://github.com/qixuanl1), Google LLC |
||||
- [ran-su](https://github.com/ran-su), Google LLC |
||||
- [rmstar](https://github.com/rmstar), Google LLC |
||||
- [sanjaypujare](https://github.com/sanjaypujare), Google LLC |
||||
- [sheenaqotj](https://github.com/sheenaqotj), Google LLC |
||||
- [soheilhy](https://github.com/soheilhy), Google LLC |
||||
- [sreecha](https://github.com/sreecha), LinkedIn |
||||
- [srini100](https://github.com/srini100), Google LLC |
||||
- [stanley-cheung](https://github.com/stanley-cheung), Google LLC |
||||
- [veblush](https://github.com/veblush), Google LLC |
||||
- [vishalpowar](https://github.com/vishalpowar), Google LLC |
||||
- [Vizerai](https://github.com/Vizerai), Google LLC |
||||
- [vjpai](https://github.com/vjpai), Google LLC |
||||
- [wcevans](https://github.com/wcevans), Google LLC |
||||
- [wenbozhu](https://github.com/wenbozhu), Google LLC |
||||
- [yang-g](https://github.com/yang-g), Google LLC |
||||
- [yashykt](https://github.com/yashykt), Google LLC |
||||
- [yihuazhang](https://github.com/yihuazhang), Google LLC |
||||
- [ZhouyihaiDing](https://github.com/ZhouyihaiDing), Google LLC |
||||
|
||||
|
||||
## Emeritus Maintainers (in alphabetical order) |
||||
- [adelez](https://github.com/adelez), Google LLC |
||||
- [billfeng327](https://github.com/billfeng327), Google LLC |
||||
- [ctiller](https://github.com/ctiller), Google LLC |
||||
- [dgquintas](https://github.com/dgquintas), Google LLC |
||||
- [ericgribkoff](https://github.com/ericgribkoff), Google LLC |
||||
- [fengli79](https://github.com/fengli79), Google LLC |
||||
- [jcanizales](https://github.com/jcanizales), Google LLC |
||||
- [jpalmerLinuxFoundation](https://github.com/jpalmerLinuxFoundation), Linux Foundation |
||||
- [justinburke](https://github.com/justinburke), Google LLC |
||||
- [kpayson64](https://github.com/kpayson64), Google LLC |
||||
- [lyuxuan](https://github.com/lyuxuan), Google LLC |
||||
- [matt-kwong](https://github.com/matt-kwong), Google LLC |
||||
- [mit-mit](https://github.com/mit-mit), Google LLC |
||||
- [mpwarres](https://github.com/mpwarres), Google LLC |
||||
- [ncteisen](https://github.com/ncteisen), Google LLC |
||||
- [pmarks-net](https://github.com/pmarks-net), Google LLC |
||||
- [slash-lib](https://github.com/slash-lib), Google LLC |
||||
- [soltanmm](https://github.com/soltanmm), Google LLC |
||||
- [summerxyt](https://github.com/summerxyt), Google LLC |
||||
- [y-zeng](https://github.com/y-zeng), Google LLC |
||||
- [zpencer](https://github.com/zpencer), Google LLC |
@ -0,0 +1,12 @@ |
||||
prefix=@CMAKE_INSTALL_PREFIX@ |
||||
exec_prefix=${prefix} |
||||
includedir=${prefix}/include |
||||
libdir=${exec_prefix}/lib |
||||
|
||||
Name: @PC_NAME@ |
||||
Description: @PC_DESCRIPTION@ |
||||
Version: @PC_VERSION@ |
||||
Cflags: -I${includedir} |
||||
Requires: @PC_REQUIRES@ |
||||
Libs: -L${libdir} @PC_LIB@ |
||||
Libs.private: @PC_LIBS_PRIVATE@ |
@ -0,0 +1,8 @@ |
||||
*.o |
||||
*.pb.cc |
||||
*.pb.h |
||||
greeter_client |
||||
greeter_server |
||||
greeter_async_client |
||||
greeter_async_client2 |
||||
greeter_async_server |
@ -0,0 +1,86 @@ |
||||
|
||||
# gRPC PHP End-to-End Examples |
||||
|
||||
This page shows a number of ways to create a PHP gRPC client and connect with |
||||
a gRPC backend service. |
||||
|
||||
|
||||
## Run the Server |
||||
|
||||
For all the following examples, we use a simple gRPC server, written in Node. |
||||
|
||||
```sh |
||||
$ git clone https://github.com/grpc/grpc-web |
||||
$ cd grpc-web |
||||
$ docker-compose build common node-server |
||||
$ docker run -d -p 9090:9090 --name node-server grpcweb/node-server |
||||
``` |
||||
|
||||
|
||||
## Install the gRPC PECL extension |
||||
|
||||
All the following commands are assumed to be run from this current directory. |
||||
|
||||
```sh |
||||
$ cd grpc/examples/php/echo |
||||
``` |
||||
|
||||
|
||||
In order to build a PHP gRPC client, we need to install the `grpc` extension |
||||
first. |
||||
|
||||
```sh |
||||
$ docker build -t grpc-php/base -f ./base.Dockerfile . |
||||
``` |
||||
|
||||
|
||||
## CLI |
||||
|
||||
|
||||
Let's first build a simple CLI gRPC client: |
||||
|
||||
```sh |
||||
$ docker build -t grpc-php/echo-client -f ./cli.Dockerfile . |
||||
$ docker run -it --rm --link node-server:node-server grpc-php/echo-client |
||||
$ php client.php |
||||
``` |
||||
|
||||
|
||||
|
||||
## Apache |
||||
|
||||
|
||||
Now let's see how the gRPC PHP client can run with Apache: |
||||
|
||||
```sh |
||||
$ docker build -t grpc-php/apache -f ./apache.Dockerfile . |
||||
$ docker run -it --rm --link node-server:node-server -p 80:80 grpc-php/apache |
||||
``` |
||||
|
||||
Open the browser to `http://localhost`. |
||||
|
||||
|
||||
|
||||
## Nginx + FPM |
||||
|
||||
|
||||
We can also try running PHP-FPM and put Nginx in front of it. |
||||
|
||||
|
||||
The PHP-FPM part: |
||||
|
||||
```sh |
||||
$ docker build -t grpc-php/fpm -f ./fpm.Dockerfile . |
||||
$ docker run -it --rm --link node-server:node-server -p 9000:9000 \ |
||||
--name fpm grpc-php/fpm |
||||
``` |
||||
|
||||
The Nginx part: |
||||
|
||||
```sh |
||||
$ docker run -it --rm -v $(pwd)/nginx.conf:/etc/nginx/conf.d/default.conf:ro \ |
||||
--link fpm:fpm -p 80:80 nginx:1.17.4 |
||||
``` |
||||
|
||||
|
||||
Open the browser to `http://localhost`. |
@ -0,0 +1,49 @@ |
||||
# Copyright 2019 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
|
||||
FROM composer:1.8.6 as composer |
||||
|
||||
|
||||
FROM grpc-php/base as grpc-base |
||||
|
||||
|
||||
FROM php:7.2-apache-stretch |
||||
|
||||
RUN apt-get -qq update && apt-get -qq install -y git |
||||
|
||||
|
||||
COPY --from=composer /usr/bin/composer /usr/bin/composer |
||||
|
||||
COPY --from=grpc-base /usr/local/bin/protoc /usr/local/bin/protoc |
||||
|
||||
COPY --from=grpc-base /github/grpc/bins/opt/grpc_php_plugin \ |
||||
/usr/local/bin/protoc-gen-grpc |
||||
|
||||
COPY --from=grpc-base \ |
||||
/usr/local/lib/php/extensions/no-debug-non-zts-20170718/grpc.so \ |
||||
/usr/local/lib/php/extensions/no-debug-non-zts-20170718/grpc.so |
||||
|
||||
|
||||
RUN docker-php-ext-enable grpc |
||||
|
||||
|
||||
WORKDIR /var/www/html |
||||
|
||||
COPY client.php ./index.php |
||||
COPY composer.json . |
||||
COPY echo.proto . |
||||
|
||||
RUN protoc -I=. echo.proto --php_out=. --grpc_out=. |
||||
|
||||
RUN composer install |
@ -0,0 +1,38 @@ |
||||
# Copyright 2019 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
|
||||
FROM php:7.2-stretch |
||||
|
||||
RUN apt-get -qq update && apt-get -qq install -y \ |
||||
autoconf automake curl git libtool \ |
||||
pkg-config unzip zlib1g-dev |
||||
|
||||
|
||||
WORKDIR /tmp |
||||
|
||||
RUN curl -sSL https://github.com/protocolbuffers/protobuf/releases/download/v3.8.0/\ |
||||
protoc-3.8.0-linux-x86_64.zip -o /tmp/protoc.zip && \ |
||||
unzip -qq protoc.zip && \ |
||||
cp /tmp/bin/protoc /usr/local/bin/protoc |
||||
|
||||
|
||||
WORKDIR /github/grpc |
||||
|
||||
RUN git clone https://github.com/grpc/grpc . && \ |
||||
git submodule update --init && \ |
||||
cd third_party/protobuf && git submodule update --init |
||||
|
||||
RUN make grpc_php_plugin |
||||
|
||||
RUN pecl install grpc |
@ -0,0 +1,52 @@ |
||||
# Copyright 2019 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
|
||||
FROM composer:1.8.6 as composer |
||||
|
||||
|
||||
FROM grpc-php/base as grpc-base |
||||
|
||||
|
||||
FROM php:7.2-stretch |
||||
|
||||
RUN apt-get -qq update && apt-get -qq install -y git |
||||
|
||||
|
||||
COPY --from=composer /usr/bin/composer /usr/bin/composer |
||||
|
||||
COPY --from=grpc-base /usr/local/bin/protoc /usr/local/bin/protoc |
||||
|
||||
COPY --from=grpc-base /github/grpc/bins/opt/grpc_php_plugin \ |
||||
/usr/local/bin/protoc-gen-grpc |
||||
|
||||
COPY --from=grpc-base \ |
||||
/usr/local/lib/php/extensions/no-debug-non-zts-20170718/grpc.so \ |
||||
/usr/local/lib/php/extensions/no-debug-non-zts-20170718/grpc.so |
||||
|
||||
|
||||
RUN docker-php-ext-enable grpc |
||||
|
||||
|
||||
WORKDIR /github/grpc-php/examples/echo |
||||
|
||||
COPY client.php . |
||||
COPY composer.json . |
||||
COPY echo.proto . |
||||
|
||||
RUN protoc -I=. echo.proto --php_out=. --grpc_out=. |
||||
|
||||
RUN composer install |
||||
|
||||
|
||||
CMD ["/bin/bash"] |
@ -0,0 +1,45 @@ |
||||
<?php |
||||
/* |
||||
* |
||||
* Copyright 2018 gRPC authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
* |
||||
*/ |
||||
|
||||
require dirname(__FILE__).'/vendor/autoload.php'; |
||||
|
||||
$client = new Grpc\Gateway\Testing\EchoServiceClient('node-server:9090', [ |
||||
'credentials' => Grpc\ChannelCredentials::createInsecure(), |
||||
]); |
||||
|
||||
|
||||
// unary call |
||||
$request = new Grpc\Gateway\Testing\EchoRequest(); |
||||
$request->setMessage("Hello World!"); |
||||
|
||||
list($response, $status) = $client->Echo($request)->wait(); |
||||
|
||||
echo $response->getMessage()."\n"; |
||||
|
||||
|
||||
// server streaming call |
||||
$stream_request = new Grpc\Gateway\Testing\ServerStreamingEchoRequest(); |
||||
$stream_request->setMessage("stream message"); |
||||
$stream_request->setMessageCount(5); |
||||
|
||||
$responses = $client->ServerStreamingEcho($stream_request)->responses(); |
||||
|
||||
foreach ($responses as $response) { |
||||
echo $response->getMessage()."\n"; |
||||
} |
@ -0,0 +1,12 @@ |
||||
{ |
||||
"name": "grpc-php/echo-example", |
||||
"require": { |
||||
"grpc/grpc": "^v1.22.0", |
||||
"google/protobuf": "^3.7.0" |
||||
}, |
||||
"autoload": { |
||||
"psr-4": { |
||||
"": "./" |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,100 @@ |
||||
// Copyright 2019 gRPC authors. |
||||
// |
||||
// Licensed under the Apache License, Version 2.0 (the "License"); |
||||
// you may not use this file except in compliance with the License. |
||||
// You may obtain a copy of the License at |
||||
// |
||||
// http://www.apache.org/licenses/LICENSE-2.0 |
||||
// |
||||
// Unless required by applicable law or agreed to in writing, software |
||||
// distributed under the License is distributed on an "AS IS" BASIS, |
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
// See the License for the specific language governing permissions and |
||||
// limitations under the License. |
||||
|
||||
syntax = "proto3"; |
||||
|
||||
package grpc.gateway.testing; |
||||
|
||||
message Empty {} |
||||
|
||||
message EchoRequest { |
||||
string message = 1; |
||||
} |
||||
|
||||
message EchoResponse { |
||||
string message = 1; |
||||
int32 message_count = 2; |
||||
} |
||||
|
||||
// Request type for server side streaming echo. |
||||
message ServerStreamingEchoRequest { |
||||
// Message string for server streaming request. |
||||
string message = 1; |
||||
|
||||
// The total number of messages to be generated before the server |
||||
// closes the stream; default is 10. |
||||
int32 message_count = 2; |
||||
|
||||
// The interval (ms) between two server messages. The server implementation |
||||
// may enforce some minimum interval (e.g. 100ms) to avoid message overflow. |
||||
int32 message_interval = 3; |
||||
} |
||||
|
||||
// Response type for server streaming response. |
||||
message ServerStreamingEchoResponse { |
||||
// Response message. |
||||
string message = 1; |
||||
} |
||||
|
||||
// Request type for client side streaming echo. |
||||
message ClientStreamingEchoRequest { |
||||
// A special value "" indicates that there's no further messages. |
||||
string message = 1; |
||||
} |
||||
|
||||
// Response type for client side streaming echo. |
||||
message ClientStreamingEchoResponse { |
||||
// Total number of client messages that have been received. |
||||
int32 message_count = 1; |
||||
} |
||||
|
||||
// A simple echo service. |
||||
service EchoService { |
||||
// One request followed by one response |
||||
// The server returns the client message as-is. |
||||
rpc Echo(EchoRequest) returns (EchoResponse); |
||||
|
||||
// Sends back abort status. |
||||
rpc EchoAbort(EchoRequest) returns (EchoResponse) {} |
||||
|
||||
// One empty request, ZERO processing, followed by one empty response |
||||
// (minimum effort to do message serialization). |
||||
rpc NoOp(Empty) returns (Empty); |
||||
|
||||
// One request followed by a sequence of responses (streamed download). |
||||
// The server will return the same client message repeatedly. |
||||
rpc ServerStreamingEcho(ServerStreamingEchoRequest) |
||||
returns (stream ServerStreamingEchoResponse); |
||||
|
||||
// One request followed by a sequence of responses (streamed download). |
||||
// The server abort directly. |
||||
rpc ServerStreamingEchoAbort(ServerStreamingEchoRequest) |
||||
returns (stream ServerStreamingEchoResponse) {} |
||||
|
||||
// A sequence of requests followed by one response (streamed upload). |
||||
// The server returns the total number of messages as the result. |
||||
rpc ClientStreamingEcho(stream ClientStreamingEchoRequest) |
||||
returns (ClientStreamingEchoResponse); |
||||
|
||||
// A sequence of requests with each message echoed by the server immediately. |
||||
// The server returns the same client messages in order. |
||||
// E.g. this is how the speech API works. |
||||
rpc FullDuplexEcho(stream EchoRequest) returns (stream EchoResponse); |
||||
|
||||
// A sequence of requests followed by a sequence of responses. |
||||
// The server buffers all the client messages and then returns the same |
||||
// client messages one by one after the client half-closes the stream. |
||||
// This is how an image recognition API may work. |
||||
rpc HalfDuplexEcho(stream EchoRequest) returns (stream EchoResponse); |
||||
} |
@ -0,0 +1,49 @@ |
||||
# Copyright 2019 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
|
||||
FROM composer:1.8.6 as composer |
||||
|
||||
|
||||
FROM grpc-php/base as grpc-base |
||||
|
||||
|
||||
FROM php:7.2-fpm-stretch |
||||
|
||||
RUN apt-get -qq update && apt-get -qq install -y git |
||||
|
||||
|
||||
COPY --from=composer /usr/bin/composer /usr/bin/composer |
||||
|
||||
COPY --from=grpc-base /usr/local/bin/protoc /usr/local/bin/protoc |
||||
|
||||
COPY --from=grpc-base /github/grpc/bins/opt/grpc_php_plugin \ |
||||
/usr/local/bin/protoc-gen-grpc |
||||
|
||||
COPY --from=grpc-base \ |
||||
/usr/local/lib/php/extensions/no-debug-non-zts-20170718/grpc.so \ |
||||
/usr/local/lib/php/extensions/no-debug-non-zts-20170718/grpc.so |
||||
|
||||
|
||||
RUN docker-php-ext-enable grpc |
||||
|
||||
|
||||
WORKDIR /var/www/html |
||||
|
||||
COPY client.php ./index.php |
||||
COPY composer.json . |
||||
COPY echo.proto . |
||||
|
||||
RUN protoc -I=. echo.proto --php_out=. --grpc_out=. |
||||
|
||||
RUN composer install |
@ -0,0 +1,23 @@ |
||||
server { |
||||
listen 80; |
||||
server_name localhost; |
||||
root /var/www/html; |
||||
|
||||
index index.php; |
||||
|
||||
location / { |
||||
try_files $uri $uri/ /index.php?$args; |
||||
} |
||||
|
||||
location ~ [^/]\.php(/|$) { |
||||
fastcgi_split_path_info ^(.+?\.php)(/.*)$; |
||||
|
||||
include fastcgi_params; |
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; |
||||
fastcgi_param PATH_INFO $fastcgi_path_info; |
||||
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; |
||||
|
||||
fastcgi_pass fpm:9000; |
||||
fastcgi_index index.php; |
||||
} |
||||
} |
@ -0,0 +1,36 @@ |
||||
## Data transmission demo for using gRPC in Python |
||||
|
||||
在Python中使用gRPC时, 进行数据传输的四种方式 [官方指南](<https://grpc.io/docs/guides/concepts/#unary-rpc>) |
||||
|
||||
- #### 一元模式 |
||||
|
||||
在一次调用中, 客户端只能向服务器传输一次请求数据, 服务器也只能返回一次响应 |
||||
|
||||
`client.py: simple_method` |
||||
|
||||
`server.py: SimpleMethod` |
||||
|
||||
- #### 客户端流模式 |
||||
|
||||
在一次调用中, 客户端可以多次向服务器传输数据, 但是服务器只能返回一次响应 |
||||
|
||||
`client.py: client_streaming_method ` |
||||
|
||||
`server.py: ClientStreamingMethod` |
||||
|
||||
- #### 服务端流模式 |
||||
|
||||
在一次调用中, 客户端只能向服务器传输一次请求数据, 但是服务器可以多次返回响应 |
||||
|
||||
`client.py: server_streaming_method` |
||||
|
||||
`server.py: ServerStreamingMethod` |
||||
|
||||
- #### 双向流模式 |
||||
|
||||
在一次调用中, 客户端和服务器都可以向对方多次收发数据 |
||||
|
||||
`client.py: bidirectional_streaming_method` |
||||
|
||||
`server.py: BidirectionalStreamingMethod` |
||||
|
@ -0,0 +1,37 @@ |
||||
## Data transmission demo for using gRPC in Python |
||||
|
||||
Four ways of data transmission when gRPC is used in Python. [Official Guide](<https://grpc.io/docs/guides/concepts/#unary-rpc>) |
||||
|
||||
- #### unary-unary |
||||
|
||||
In a single call, the client can only send request once, and the server can only respond once. |
||||
|
||||
`client.py: simple_method` |
||||
|
||||
`server.py: SimpleMethod` |
||||
|
||||
- #### stream-unary |
||||
|
||||
In a single call, the client can transfer data to the server an arbitrary number of times, but the server can only return a response once. |
||||
|
||||
`client.py: client_streaming_method` |
||||
|
||||
`server.py: ClientStreamingMethod` |
||||
|
||||
- #### unary-stream |
||||
|
||||
In a single call, the client can only transmit data to the server at one time, but the server can return the response many times. |
||||
|
||||
`client.py: server_streaming_method` |
||||
|
||||
`server.py: ServerStreamingMethod` |
||||
|
||||
- #### stream-stream |
||||
|
||||
In a single call, both client and server can send and receive data |
||||
to each other multiple times. |
||||
|
||||
`client.py: bidirectional_streaming_method` |
||||
|
||||
`server.py: BidirectionalStreamingMethod` |
||||
|
@ -0,0 +1,114 @@ |
||||
# Copyright 2019 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
"""The example of four ways of data transmission using gRPC in Python.""" |
||||
|
||||
import time |
||||
import grpc |
||||
|
||||
import demo_pb2_grpc |
||||
import demo_pb2 |
||||
|
||||
SERVER_ADDRESS = "localhost:23333" |
||||
CLIENT_ID = 1 |
||||
|
||||
|
||||
# 一元模式(在一次调用中, 客户端只能向服务器传输一次请求数据, 服务器也只能返回一次响应) |
||||
# unary-unary(In a single call, the client can only send request once, and the server can |
||||
# only respond once.) |
||||
def simple_method(stub): |
||||
print("--------------Call SimpleMethod Begin--------------") |
||||
request = demo_pb2.Request( |
||||
client_id=CLIENT_ID, request_data="called by Python client") |
||||
response = stub.SimpleMethod(request) |
||||
print("resp from server(%d), the message=%s" % (response.server_id, |
||||
response.response_data)) |
||||
print("--------------Call SimpleMethod Over---------------") |
||||
|
||||
|
||||
# 客户端流模式(在一次调用中, 客户端可以多次向服务器传输数据, 但是服务器只能返回一次响应) |
||||
# stream-unary (In a single call, the client can transfer data to the server several times, |
||||
# but the server can only return a response once.) |
||||
def client_streaming_method(stub): |
||||
print("--------------Call ClientStreamingMethod Begin--------------") |
||||
|
||||
# 创建一个生成器 |
||||
# create a generator |
||||
def request_messages(): |
||||
for i in range(5): |
||||
request = demo_pb2.Request( |
||||
client_id=CLIENT_ID, |
||||
request_data=("called by Python client, message:%d" % i)) |
||||
yield request |
||||
|
||||
response = stub.ClientStreamingMethod(request_messages()) |
||||
print("resp from server(%d), the message=%s" % (response.server_id, |
||||
response.response_data)) |
||||
print("--------------Call ClientStreamingMethod Over---------------") |
||||
|
||||
|
||||
# 服务端流模式(在一次调用中, 客户端只能一次向服务器传输数据, 但是服务器可以多次返回响应) |
||||
# unary-stream (In a single call, the client can only transmit data to the server at one time, |
||||
# but the server can return the response many times.) |
||||
def server_streaming_method(stub): |
||||
print("--------------Call ServerStreamingMethod Begin--------------") |
||||
request = demo_pb2.Request( |
||||
client_id=CLIENT_ID, request_data="called by Python client") |
||||
response_iterator = stub.ServerStreamingMethod(request) |
||||
for response in response_iterator: |
||||
print("recv from server(%d), message=%s" % (response.server_id, |
||||
response.response_data)) |
||||
|
||||
print("--------------Call ServerStreamingMethod Over---------------") |
||||
|
||||
|
||||
# 双向流模式 (在一次调用中, 客户端和服务器都可以向对方多次收发数据) |
||||
# stream-stream (In a single call, both client and server can send and receive data |
||||
# to each other multiple times.) |
||||
def bidirectional_streaming_method(stub): |
||||
print( |
||||
"--------------Call BidirectionalStreamingMethod Begin---------------") |
||||
|
||||
# 创建一个生成器 |
||||
# create a generator |
||||
def request_messages(): |
||||
for i in range(5): |
||||
request = demo_pb2.Request( |
||||
client_id=CLIENT_ID, |
||||
request_data=("called by Python client, message: %d" % i)) |
||||
yield request |
||||
time.sleep(1) |
||||
|
||||
response_iterator = stub.BidirectionalStreamingMethod(request_messages()) |
||||
for response in response_iterator: |
||||
print("recv from server(%d), message=%s" % (response.server_id, |
||||
response.response_data)) |
||||
|
||||
print("--------------Call BidirectionalStreamingMethod Over---------------") |
||||
|
||||
|
||||
def main(): |
||||
with grpc.insecure_channel(SERVER_ADDRESS) as channel: |
||||
stub = demo_pb2_grpc.GRPCDemoStub(channel) |
||||
|
||||
simple_method(stub) |
||||
|
||||
client_streaming_method(stub) |
||||
|
||||
server_streaming_method(stub) |
||||
|
||||
bidirectional_streaming_method(stub) |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
main() |
@ -0,0 +1,69 @@ |
||||
// Copyright 2019 gRPC authors. |
||||
// |
||||
// Licensed under the Apache License, Version 2.0 (the "License"); |
||||
// you may not use this file except in compliance with the License. |
||||
// You may obtain a copy of the License at |
||||
// |
||||
// http://www.apache.org/licenses/LICENSE-2.0 |
||||
// |
||||
// Unless required by applicable law or agreed to in writing, software |
||||
// distributed under the License is distributed on an "AS IS" BASIS, |
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
// See the License for the specific language governing permissions and |
||||
// limitations under the License. |
||||
|
||||
// 语法版本声明,必须放在非注释的第一行 |
||||
// Syntax version declaration. Must be placed on the first line of non-commentary. |
||||
|
||||
syntax = "proto3"; |
||||
// The document of proto3: https://developers.google.com/protocol-buffers/docs/proto3 |
||||
|
||||
// 包名定义, Python中使用时可以省略不写 |
||||
// Package name definition, which can be omitted in Python. |
||||
package demo; |
||||
|
||||
/* |
||||
`message`是用来定义传输的数据的格式的, 等号后面的是字段编号 |
||||
消息定义中的每个字段都有唯一的编号 |
||||
总体格式类似于Python中定义一个类或者Golang中定义一个结构体 |
||||
*/ |
||||
/* |
||||
`message` is used to define the structure of the data to be transmitted, after the equal sign |
||||
is the field number. Each field in the message definition has a unique number. |
||||
The overall format is similar to defining a class in Python or a structure in Golang. |
||||
*/ |
||||
message Request { |
||||
int64 client_id = 1; |
||||
string request_data = 2; |
||||
} |
||||
|
||||
message Response { |
||||
int64 server_id = 1; |
||||
string response_data = 2; |
||||
} |
||||
|
||||
// `service` 是用来给gRPC服务定义方法的, 格式固定, 类似于Golang中定义一个接口 |
||||
// `service` is used to define methods for gRPC services in a fixed format, similar to defining |
||||
//an interface in Golang |
||||
service GRPCDemo { |
||||
// 一元模式(在一次调用中, 客户端只能向服务器传输一次请求数据, 服务器也只能返回一次响应) |
||||
// unary-unary(In a single call, the client can only send request once, and the server can |
||||
// only respond once.) |
||||
rpc SimpleMethod (Request) returns (Response); |
||||
|
||||
// 客户端流模式(在一次调用中, 客户端可以多次向服务器传输数据, 但是服务器只能返回一次响应) |
||||
// stream-unary (In a single call, the client can transfer data to the server several times, |
||||
// but the server can only return a response once.) |
||||
rpc ClientStreamingMethod (stream Request) returns (Response); |
||||
|
||||
// 服务端流模式(在一次调用中, 客户端只能一次向服务器传输数据, 但是服务器可以多次返回响应) |
||||
// unary-stream (In a single call, the client can only transmit data to the server at one time, |
||||
// but the server can return the response many times.) |
||||
rpc ServerStreamingMethod (Request) returns (stream Response); |
||||
|
||||
// 双向流模式 (在一次调用中, 客户端和服务器都可以向对方多次收发数据) |
||||
// stream-stream (In a single call, both client and server can send and receive data |
||||
// to each other multiple times.) |
||||
rpc BidirectionalStreamingMethod (stream Request) returns (stream Response); |
||||
} |
||||
|
@ -0,0 +1,174 @@ |
||||
# -*- coding: utf-8 -*- |
||||
# Generated by the protocol buffer compiler. DO NOT EDIT! |
||||
# source: demo.proto |
||||
|
||||
import sys |
||||
_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1')) |
||||
from google.protobuf import descriptor as _descriptor |
||||
from google.protobuf import message as _message |
||||
from google.protobuf import reflection as _reflection |
||||
from google.protobuf import symbol_database as _symbol_database |
||||
# @@protoc_insertion_point(imports) |
||||
|
||||
_sym_db = _symbol_database.Default() |
||||
|
||||
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor.FileDescriptor( |
||||
name='demo.proto', |
||||
package='demo', |
||||
syntax='proto3', |
||||
serialized_options=None, |
||||
serialized_pb=_b('\n\ndemo.proto\x12\x04\x64\x65mo\"2\n\x07Request\x12\x11\n\tclient_id\x18\x01 \x01(\x03\x12\x14\n\x0crequest_data\x18\x02 \x01(\t\"4\n\x08Response\x12\x11\n\tserver_id\x18\x01 \x01(\x03\x12\x15\n\rresponse_data\x18\x02 \x01(\t2\xf0\x01\n\x08GRPCDemo\x12-\n\x0cSimpleMethod\x12\r.demo.Request\x1a\x0e.demo.Response\x12\x38\n\x15\x43lientStreamingMethod\x12\r.demo.Request\x1a\x0e.demo.Response(\x01\x12\x38\n\x15ServerStreamingMethod\x12\r.demo.Request\x1a\x0e.demo.Response0\x01\x12\x41\n\x1c\x42idirectionalStreamingMethod\x12\r.demo.Request\x1a\x0e.demo.Response(\x01\x30\x01\x62\x06proto3') |
||||
) |
||||
|
||||
|
||||
|
||||
|
||||
_REQUEST = _descriptor.Descriptor( |
||||
name='Request', |
||||
full_name='demo.Request', |
||||
filename=None, |
||||
file=DESCRIPTOR, |
||||
containing_type=None, |
||||
fields=[ |
||||
_descriptor.FieldDescriptor( |
||||
name='client_id', full_name='demo.Request.client_id', index=0, |
||||
number=1, type=3, cpp_type=2, label=1, |
||||
has_default_value=False, default_value=0, |
||||
message_type=None, enum_type=None, containing_type=None, |
||||
is_extension=False, extension_scope=None, |
||||
serialized_options=None, file=DESCRIPTOR), |
||||
_descriptor.FieldDescriptor( |
||||
name='request_data', full_name='demo.Request.request_data', index=1, |
||||
number=2, type=9, cpp_type=9, label=1, |
||||
has_default_value=False, default_value=_b("").decode('utf-8'), |
||||
message_type=None, enum_type=None, containing_type=None, |
||||
is_extension=False, extension_scope=None, |
||||
serialized_options=None, file=DESCRIPTOR), |
||||
], |
||||
extensions=[ |
||||
], |
||||
nested_types=[], |
||||
enum_types=[ |
||||
], |
||||
serialized_options=None, |
||||
is_extendable=False, |
||||
syntax='proto3', |
||||
extension_ranges=[], |
||||
oneofs=[ |
||||
], |
||||
serialized_start=20, |
||||
serialized_end=70, |
||||
) |
||||
|
||||
|
||||
_RESPONSE = _descriptor.Descriptor( |
||||
name='Response', |
||||
full_name='demo.Response', |
||||
filename=None, |
||||
file=DESCRIPTOR, |
||||
containing_type=None, |
||||
fields=[ |
||||
_descriptor.FieldDescriptor( |
||||
name='server_id', full_name='demo.Response.server_id', index=0, |
||||
number=1, type=3, cpp_type=2, label=1, |
||||
has_default_value=False, default_value=0, |
||||
message_type=None, enum_type=None, containing_type=None, |
||||
is_extension=False, extension_scope=None, |
||||
serialized_options=None, file=DESCRIPTOR), |
||||
_descriptor.FieldDescriptor( |
||||
name='response_data', full_name='demo.Response.response_data', index=1, |
||||
number=2, type=9, cpp_type=9, label=1, |
||||
has_default_value=False, default_value=_b("").decode('utf-8'), |
||||
message_type=None, enum_type=None, containing_type=None, |
||||
is_extension=False, extension_scope=None, |
||||
serialized_options=None, file=DESCRIPTOR), |
||||
], |
||||
extensions=[ |
||||
], |
||||
nested_types=[], |
||||
enum_types=[ |
||||
], |
||||
serialized_options=None, |
||||
is_extendable=False, |
||||
syntax='proto3', |
||||
extension_ranges=[], |
||||
oneofs=[ |
||||
], |
||||
serialized_start=72, |
||||
serialized_end=124, |
||||
) |
||||
|
||||
DESCRIPTOR.message_types_by_name['Request'] = _REQUEST |
||||
DESCRIPTOR.message_types_by_name['Response'] = _RESPONSE |
||||
_sym_db.RegisterFileDescriptor(DESCRIPTOR) |
||||
|
||||
Request = _reflection.GeneratedProtocolMessageType('Request', (_message.Message,), { |
||||
'DESCRIPTOR' : _REQUEST, |
||||
'__module__' : 'demo_pb2' |
||||
# @@protoc_insertion_point(class_scope:demo.Request) |
||||
}) |
||||
_sym_db.RegisterMessage(Request) |
||||
|
||||
Response = _reflection.GeneratedProtocolMessageType('Response', (_message.Message,), { |
||||
'DESCRIPTOR' : _RESPONSE, |
||||
'__module__' : 'demo_pb2' |
||||
# @@protoc_insertion_point(class_scope:demo.Response) |
||||
}) |
||||
_sym_db.RegisterMessage(Response) |
||||
|
||||
|
||||
|
||||
_GRPCDEMO = _descriptor.ServiceDescriptor( |
||||
name='GRPCDemo', |
||||
full_name='demo.GRPCDemo', |
||||
file=DESCRIPTOR, |
||||
index=0, |
||||
serialized_options=None, |
||||
serialized_start=127, |
||||
serialized_end=367, |
||||
methods=[ |
||||
_descriptor.MethodDescriptor( |
||||
name='SimpleMethod', |
||||
full_name='demo.GRPCDemo.SimpleMethod', |
||||
index=0, |
||||
containing_service=None, |
||||
input_type=_REQUEST, |
||||
output_type=_RESPONSE, |
||||
serialized_options=None, |
||||
), |
||||
_descriptor.MethodDescriptor( |
||||
name='ClientStreamingMethod', |
||||
full_name='demo.GRPCDemo.ClientStreamingMethod', |
||||
index=1, |
||||
containing_service=None, |
||||
input_type=_REQUEST, |
||||
output_type=_RESPONSE, |
||||
serialized_options=None, |
||||
), |
||||
_descriptor.MethodDescriptor( |
||||
name='ServerStreamingMethod', |
||||
full_name='demo.GRPCDemo.ServerStreamingMethod', |
||||
index=2, |
||||
containing_service=None, |
||||
input_type=_REQUEST, |
||||
output_type=_RESPONSE, |
||||
serialized_options=None, |
||||
), |
||||
_descriptor.MethodDescriptor( |
||||
name='BidirectionalStreamingMethod', |
||||
full_name='demo.GRPCDemo.BidirectionalStreamingMethod', |
||||
index=3, |
||||
containing_service=None, |
||||
input_type=_REQUEST, |
||||
output_type=_RESPONSE, |
||||
serialized_options=None, |
||||
), |
||||
]) |
||||
_sym_db.RegisterServiceDescriptor(_GRPCDEMO) |
||||
|
||||
DESCRIPTOR.services_by_name['GRPCDemo'] = _GRPCDEMO |
||||
|
||||
# @@protoc_insertion_point(module_scope) |
@ -0,0 +1,106 @@ |
||||
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! |
||||
import grpc |
||||
|
||||
import demo_pb2 as demo__pb2 |
||||
|
||||
|
||||
class GRPCDemoStub(object): |
||||
"""service是用来给GRPC服务定义方法的, 格式固定, 类似于Golang中定义一个接口 |
||||
`service` is used to define methods for GRPC services in a fixed format, similar to defining an interface in Golang |
||||
""" |
||||
|
||||
def __init__(self, channel): |
||||
"""Constructor. |
||||
|
||||
Args: |
||||
channel: A grpc.Channel. |
||||
""" |
||||
self.SimpleMethod = channel.unary_unary( |
||||
'/demo.GRPCDemo/SimpleMethod', |
||||
request_serializer=demo__pb2.Request.SerializeToString, |
||||
response_deserializer=demo__pb2.Response.FromString, |
||||
) |
||||
self.ClientStreamingMethod = channel.stream_unary( |
||||
'/demo.GRPCDemo/ClientStreamingMethod', |
||||
request_serializer=demo__pb2.Request.SerializeToString, |
||||
response_deserializer=demo__pb2.Response.FromString, |
||||
) |
||||
self.ServerStreamingMethod = channel.unary_stream( |
||||
'/demo.GRPCDemo/ServerStreamingMethod', |
||||
request_serializer=demo__pb2.Request.SerializeToString, |
||||
response_deserializer=demo__pb2.Response.FromString, |
||||
) |
||||
self.BidirectionalStreamingMethod = channel.stream_stream( |
||||
'/demo.GRPCDemo/BidirectionalStreamingMethod', |
||||
request_serializer=demo__pb2.Request.SerializeToString, |
||||
response_deserializer=demo__pb2.Response.FromString, |
||||
) |
||||
|
||||
|
||||
class GRPCDemoServicer(object): |
||||
"""service是用来给GRPC服务定义方法的, 格式固定, 类似于Golang中定义一个接口 |
||||
`service` is used to define methods for GRPC services in a fixed format, similar to defining an interface in Golang |
||||
""" |
||||
|
||||
def SimpleMethod(self, request, context): |
||||
"""简单模式 |
||||
unary-unary |
||||
""" |
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED) |
||||
context.set_details('Method not implemented!') |
||||
raise NotImplementedError('Method not implemented!') |
||||
|
||||
def ClientStreamingMethod(self, request_iterator, context): |
||||
"""客户端流模式(在一次调用中, 客户端可以多次向服务器传输数据, 但是服务器只能返回一次响应) |
||||
stream-unary (In a single call, the client can transfer data to the server several times, |
||||
but the server can only return a response once.) |
||||
""" |
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED) |
||||
context.set_details('Method not implemented!') |
||||
raise NotImplementedError('Method not implemented!') |
||||
|
||||
def ServerStreamingMethod(self, request, context): |
||||
"""服务端流模式(在一次调用中, 客户端只能一次向服务器传输数据, 但是服务器可以多次返回响应) |
||||
unary-stream (In a single call, the client can only transmit data to the server at one time, |
||||
but the server can return the response many times.) |
||||
""" |
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED) |
||||
context.set_details('Method not implemented!') |
||||
raise NotImplementedError('Method not implemented!') |
||||
|
||||
def BidirectionalStreamingMethod(self, request_iterator, context): |
||||
"""双向流模式 (在一次调用中, 客户端和服务器都可以向对方多次收发数据) |
||||
stream-stream (In a single call, both client and server can send and receive data |
||||
to each other multiple times.) |
||||
""" |
||||
context.set_code(grpc.StatusCode.UNIMPLEMENTED) |
||||
context.set_details('Method not implemented!') |
||||
raise NotImplementedError('Method not implemented!') |
||||
|
||||
|
||||
def add_GRPCDemoServicer_to_server(servicer, server): |
||||
rpc_method_handlers = { |
||||
'SimpleMethod': grpc.unary_unary_rpc_method_handler( |
||||
servicer.SimpleMethod, |
||||
request_deserializer=demo__pb2.Request.FromString, |
||||
response_serializer=demo__pb2.Response.SerializeToString, |
||||
), |
||||
'ClientStreamingMethod': grpc.stream_unary_rpc_method_handler( |
||||
servicer.ClientStreamingMethod, |
||||
request_deserializer=demo__pb2.Request.FromString, |
||||
response_serializer=demo__pb2.Response.SerializeToString, |
||||
), |
||||
'ServerStreamingMethod': grpc.unary_stream_rpc_method_handler( |
||||
servicer.ServerStreamingMethod, |
||||
request_deserializer=demo__pb2.Request.FromString, |
||||
response_serializer=demo__pb2.Response.SerializeToString, |
||||
), |
||||
'BidirectionalStreamingMethod': grpc.stream_stream_rpc_method_handler( |
||||
servicer.BidirectionalStreamingMethod, |
||||
request_deserializer=demo__pb2.Request.FromString, |
||||
response_serializer=demo__pb2.Response.SerializeToString, |
||||
), |
||||
} |
||||
generic_handler = grpc.method_handlers_generic_handler( |
||||
'demo.GRPCDemo', rpc_method_handlers) |
||||
server.add_generic_rpc_handlers((generic_handler,)) |
@ -0,0 +1,114 @@ |
||||
# Copyright 2019 gRPC authors. |
||||
# |
||||
# Licensed under the Apache License, Version 2.0 (the "License"); |
||||
# you may not use this file except in compliance with the License. |
||||
# You may obtain a copy of the License at |
||||
# |
||||
# http://www.apache.org/licenses/LICENSE-2.0 |
||||
# |
||||
# Unless required by applicable law or agreed to in writing, software |
||||
# distributed under the License is distributed on an "AS IS" BASIS, |
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
# See the License for the specific language governing permissions and |
||||
# limitations under the License. |
||||
"""The example of four ways of data transmission using gRPC in Python.""" |
||||
|
||||
from threading import Thread |
||||
from concurrent import futures |
||||
|
||||
import grpc |
||||
import demo_pb2_grpc |
||||
import demo_pb2 |
||||
|
||||
SERVER_ADDRESS = 'localhost:23333' |
||||
SERVER_ID = 1 |
||||
|
||||
|
||||
class DemoServer(demo_pb2_grpc.GRPCDemoServicer): |
||||
|
||||
# 一元模式(在一次调用中, 客户端只能向服务器传输一次请求数据, 服务器也只能返回一次响应) |
||||
# unary-unary(In a single call, the client can only send request once, and the server can |
||||
# only respond once.) |
||||
def SimpleMethod(self, request, context): |
||||
print("SimpleMethod called by client(%d) the message: %s" % |
||||
(request.client_id, request.request_data)) |
||||
response = demo_pb2.Response( |
||||
server_id=SERVER_ID, |
||||
response_data="Python server SimpleMethod Ok!!!!") |
||||
return response |
||||
|
||||
# 客户端流模式(在一次调用中, 客户端可以多次向服务器传输数据, 但是服务器只能返回一次响应) |
||||
# stream-unary (In a single call, the client can transfer data to the server several times, |
||||
# but the server can only return a response once.) |
||||
def ClientStreamingMethod(self, request_iterator, context): |
||||
print("ClientStreamingMethod called by client...") |
||||
for request in request_iterator: |
||||
print("recv from client(%d), message= %s" % (request.client_id, |
||||
request.request_data)) |
||||
response = demo_pb2.Response( |
||||
server_id=SERVER_ID, |
||||
response_data="Python server ClientStreamingMethod ok") |
||||
return response |
||||
|
||||
# 服务端流模式(在一次调用中, 客户端只能一次向服务器传输数据, 但是服务器可以多次返回响应) |
||||
# unary-stream (In a single call, the client can only transmit data to the server at one time, |
||||
# but the server can return the response many times.) |
||||
def ServerStreamingMethod(self, request, context): |
||||
print("ServerStreamingMethod called by client(%d), message= %s" % |
||||
(request.client_id, request.request_data)) |
||||
|
||||
# 创建一个生成器 |
||||
# create a generator |
||||
def response_messages(): |
||||
for i in range(5): |
||||
response = demo_pb2.Response( |
||||
server_id=SERVER_ID, |
||||
response_data=("send by Python server, message=%d" % i)) |
||||
yield response |
||||
|
||||
return response_messages() |
||||
|
||||
# 双向流模式 (在一次调用中, 客户端和服务器都可以向对方多次收发数据) |
||||
# stream-stream (In a single call, both client and server can send and receive data |
||||
# to each other multiple times.) |
||||
def BidirectionalStreamingMethod(self, request_iterator, context): |
||||
print("BidirectionalStreamingMethod called by client...") |
||||
|
||||
# 开启一个子线程去接收数据 |
||||
# Open a sub thread to receive data |
||||
def parse_request(): |
||||
for request in request_iterator: |
||||
print("recv from client(%d), message= %s" % |
||||
(request.client_id, request.request_data)) |
||||
|
||||
t = Thread(target=parse_request) |
||||
t.start() |
||||
|
||||
for i in range(5): |
||||
yield demo_pb2.Response( |
||||
server_id=SERVER_ID, |
||||
response_data=("send by Python server, message= %d" % i)) |
||||
|
||||
t.join() |
||||
|
||||
|
||||
def main(): |
||||
server = grpc.server(futures.ThreadPoolExecutor()) |
||||
|
||||
demo_pb2_grpc.add_GRPCDemoServicer_to_server(DemoServer(), server) |
||||
|
||||
server.add_insecure_port(SERVER_ADDRESS) |
||||
print("------------------start Python GRPC server") |
||||
server.start() |
||||
server.wait_for_termination() |
||||
|
||||
# If raise Error: |
||||
# AttributeError: '_Server' object has no attribute 'wait_for_termination' |
||||
# You can use the following code instead: |
||||
# import time |
||||
# while 1: |
||||
# time.sleep(10) |
||||
|
||||
|
||||
if __name__ == '__main__': |
||||
main() |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue