antecedentes
El RPC normal se basa en la estructura C / S. El servidor RPC corresponde al servidor de red y el cliente RPC corresponde al cliente de red. Pero para algunos escenarios especiales, como proporcionar un servicio RPC en la intranet de la empresa, pero la extranet no se puede conectar al servidor de la intranet. En este momento, podemos referirnos a una tecnología similar al proxy inverso, primero enlazar activamente desde la red interna al servidor TCP de la red externa, y luego proporcionar servicios RPC a la red externa basados en el enlace TCP.
Declarar interfaz
type HelloService struct {}
func (p *HelloService) Hello(request string, reply *string) error {
*reply = "hello:" + request
return nil
}
Servicio RPC inverso
func main() {
rpc.Register(new(HelloService))
for {
conn, _ := net.Dial("tcp", "localhost:1234")
if conn == nil {
time.Sleep(time.Second)
continue
}
rpc.ServeConn(conn)
conn.Close()
}
}
Los servicios de intranet de RPC inverso ya no proporcionarán activamente servicios de supervisión de TCP, sino que primero se conectarán activamente al servidor TCP de la otra parte. Luego, proporcione el servicio RPC a la otra parte en función de cada enlace TCP establecido.
Cliente RPC
El cliente RPC debe proporcionar un servicio TCP en una dirección pública para aceptar solicitudes de conexión del servidor RPC:
func main() {
listener, err := net.Listen("tcp", ":1234")
if err != nil {
log.Fatal("ListenTCP error:", err)
}
clientChan := make(chan *rpc.Client)
go func() {
for {
conn, err := listener.Accept()
if err != nil {
log.Fatal("Accept error:", err)
}
clientChan <- rpc.NewClient(conn)
}
}()
doClientWork(clientChan)
}
Cuando se establece cada enlace, el objeto de cliente RPC se construye basándose en el enlace de red y se envía a la canalización clientChan.
La operación del cliente para ejecutar la llamada RPC se completa en la función doClientWork:
func doClientWork(clientChan <-chan *rpc.Client) {
client := <-clientChan
defer client.Close()
var reply string
err = client.Call("HelloService.Hello", "hello", &reply)
if err != nil {
log.Fatal(err)
}
fmt.Println(reply)
}
Primero, obtenga un objeto de cliente RPC de la canalización y use la declaración defer para especificar que el cliente se cierra antes de que salga la función. Luego, realice llamadas RPC normales.