Connect two machines using gRPC

Question:

I have a gRPC project that works correctly running server and client on the same machine, but when I try it using different machines in a same wifi network using IPV4, it occurs the following error on client:

Traceback (most recent call last):
  File "client.py", line 29, in <module>
    run()
  File "client.py", line 25, in run
    add_reply = stub.Add(add_request)
  File "/home/caio/dev/laboratorio/mygrpc/.env/lib/python3.8/site-packages/grpc/_channel.py", line 946, in __call__
    return _end_unary_response_blocking(state, call, False, None)
  File "/home/caio/dev/laboratorio/mygrpc/.env/lib/python3.8/site-packages/grpc/_channel.py", line 849, in _end_unary_response_blocking
    raise _InactiveRpcError(state)
grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
        status = StatusCode.UNAVAILABLE
        details = "failed to connect to all addresses; last error: UNKNOWN: ipv4:192.168.100.9:50051: tcp handshaker shutdown"
        debug_error_string = "UNKNOWN:failed to connect to all addresses; last error: UNKNOWN: ipv4:192.168.100.9:50051: tcp handshaker shutdown {grpc_status:14, created_time:"2022-12-10T15:21:32.619696358-03:00"}"
>

I’ve seem people reporting that it worked for them, but it’s seemed not be much different, so I have no idea what’s missing.
server code:

from os import system
system('clear')

from concurrent import futures
import time
import grpc
from grpc import _server
import sum_pb2
import sum_pb2_grpc

PORT = 50051
HOST = "localhost"

class Servicer(sum_pb2_grpc.SumNumbersServicer):
    def Add(self, request, context):
        print(request)

        add_reply = sum_pb2.AddReply()
        add_reply.r = request.a + request.b
        
        # return super().Add(request, context)
        return add_reply

def serve():
    server:_server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    sum_pb2_grpc.add_SumNumbersServicer_to_server(Servicer(), server)
    # serve._add_insecure_port(f"localhost:{PORT}")
    server.add_insecure_port(f"{HOST}:{PORT}")
    server.start()
    print(f"Listenning on port {PORT}")
    try:
        server.wait_for_termination()
    except KeyboardInterrupt:
        server.stop(0)

if __name__ == "__main__":
    serve()

client code:

from os import system
system('clear')

from concurrent import futures
import time
from random import randint
import grpc
from grpc import _server
import sum_pb2
import sum_pb2_grpc

PORT = 50051
HOST = "localhost"
HOST = "192.168.100.9"
min = 0
max = 100

def run():
    with grpc.insecure_channel(f"{HOST}:{PORT}") as channel:
        stub = sum_pb2_grpc.SumNumbersStub(channel)
        a = randint(min, max)
        b = randint(min, max)

        add_request = sum_pb2.AddRequest(a= a, b= b)
        add_reply = stub.Add(add_request)
        print(f"{a} + {b} = {add_reply}")

if __name__ == "__main__":
    run()

EDIT:
When using "0.0.0.0" as host in server.py it prints the following error (differently from last time, this time I’m using ethernet cable on both machines, idk if it makes difference ):

Traceback (most recent call last):
  File "client.py", line 29, in <module>
    run()
  File "client.py", line 25, in run
    add_reply = stub.Add(add_request)
  File "/home/estagiarioti/dev/laboratorio/mygrpc/.env/lib/python3.8/site-packages/grpc/_channel.py", line 946, in __call__
    return _end_unary_response_blocking(state, call, False, None)
  File "/home/estagiarioti/dev/laboratorio/mygrpc/.env/lib/python3.8/site-packages/grpc/_channel.py", line 849, in _end_unary_response_blocking
    raise _InactiveRpcError(state)
grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
        status = StatusCode.UNAVAILABLE
        details = "failed to connect to all addresses; last error: UNKNOWN: ipv4:192.168.10.6:50051: Failed to connect to remote host: No route to host"
        debug_error_string = "UNKNOWN:failed to connect to all addresses; last error: UNKNOWN: ipv4:192.168.10.6:50051: Failed to connect to remote host: No route to host {grpc_status:14, created_time:"2022-12-12T13:58:15.049856347-03:00"}"
>

Error message when running both machines in an wifi network and "0.0.0.0" ip in host:

Traceback (most recent call last):
  File "client.py", line 29, in <module>
    run()
  File "client.py", line 25, in run
    add_reply = stub.Add(add_request)
  File "/home/caio/dev/laboratorio/mygrpc/.env/lib/python3.8/site-packages/grpc/_channel.py", line 946, in __call__
    return _end_unary_response_blocking(state, call, False, None)
  File "/home/caio/dev/laboratorio/mygrpc/.env/lib/python3.8/site-packages/grpc/_channel.py", line 849, in _end_unary_response_blocking
    raise _InactiveRpcError(state)
grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
        status = StatusCode.UNAVAILABLE
        details = "failed to connect to all addresses; last error: UNKNOWN: ipv4:192.168.100.9:50051: tcp handshaker shutdown"
        debug_error_string = "UNKNOWN:failed to connect to all addresses; last error: UNKNOWN: ipv4:192.168.100.9:50051: tcp handshaker shutdown {created_time:"2022-12-12T19:12:13.762636131-03:00", grpc_status:14}"
>

ps: Sometimes i use WSL, sometimes i don’t, maybe this is important to know.

Asked By: Caio m. silva

||

Answers:

localhost usually resolves to 127.0.0.1 which is a special so-called loopback network address. It is used when you know that you don’t need external (to the host) connectivity because it generally doesn’t use the host’s network stack.

You will generally want to bind the server to 0.0.0.0 instead. This binds the server to all the host’s network interfaces and is a simple way to ensure that your service is available to external hosts.

Also, you will need to be confident that the server’s host’s network address is 192.168.100.9 to ensure that the client tries to communicate with the correct host.

Answered By: DazWilkin

I don’t know what I was doing wrong in WSL, but it worked when I used pure Windows and in the Firewall settings I allowed all the pythons in the list to have access in public and private networks. This with both machines on the same Wifi network

Answered By: Caio m. silva