Reputation: 859
Lets say below is the proto for bi-directional stream
service RouteGuide {
// A Bidirectional streaming RPC.
//
// Accepts a stream of RouteNotes sent while a route is being traversed,
// while receiving other RouteNotes (e.g. from other users).
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
}
Go defines an interface to send & rec messages inside a bidirectional stream from server to client & vice-versa : go interface. But I couldn't find the same in Python, to send the response inside the stream without making an additional RouteChat
call.
Also the example provided doesnt talk about sending a request back from client
How can we send the request back to server from client from python grpc clients with in the same stream?
def generate_messages():
messages = [
make_route_note("First message", 0, 0),
make_route_note("Second message", 0, 1),
make_route_note("Third message", 1, 0),
make_route_note("Fourth message", 0, 0),
make_route_note("Fifth message", 1, 0),
]
for msg in messages:
print("Sending %s at %s" % (msg.message, msg.location))
yield msg
def guide_route_chat(stub):
responses = stub.RouteChat(generate_messages())
for response in responses:
print("Received message %s at %s" % (response.message, response.location))
Upvotes: 2
Views: 215
Reputation: 67
For following proto:
syntax = "proto3";
package Streaming;
service Streaming{
rpc RpcFunction(stream Request) returns (stream Response) {}
}
message Request {
oneof stream_input {
bytes data = 1;
}
}
message Response {
oneof stream_output {
bytes data = 1;
}
}
You can send-recv message async using following function:
async with grpc.aio.insecure_channel("0.0.0.0:8001",
options=[ ('grpc.max_send_message_length', MAX_MESSAGE_LENGTH),
('grpc.max_receive_message_length', MAX_MESSAGE_LENGTH)]
) as channel:
try:
await asyncio.wait_for(channel.channel_ready(), timeout=15)
except asyncio.TimeoutError:
sys.exit('Error connecting to server')
stub = streaming_pb2_grpc.StreamingStub(channel)
stream = stub.RpcFunction()
for itr in range(0, len(msg)):
request = streaming_pb2.Request(data=msg[itr].tobytes())
await stream.write(request)
response = await stream.read()
print(response.data.decode("utf-8"))
Upvotes: 0
Reputation: 1620
For the sync stack (i.e. not asyncio), there is no API like this. Instead, you're expected to pass in an iterator of your outgoing requests. See this previous SO answer for an example of that.
The asyncio API however does have a write
/read
API that is very similar to Go's.
Upvotes: 1
Reputation: 35
You can use the same stream object to send and receive messages in a bidirectional gRPC. To send a message back to the server from the client, you can simply call the stream.write()
method on the stream object with the message you want to send.
You can change this function of yours to be this way:
def guide_route_chat(stub):
stream = stub.RouteChat(generate_messages())
for response in stream:
print("Received message %s at %s" % (response.message, response.location))
# Send a message back to the server
request = RouteNote()
request.message = "Sending message back to server."
request.location.latitude = 37.7749
request.location.longitude = -122.4194
stream.write(request)
It is important to keep in mind that the stream needs to be in active state for you to be able to send messages back. You can check this via stream.isactive()
Upvotes: -1