Maison  >  Article  >  développement back-end  >  Où le serveur Golang jsonrpc2 écoute-t-il ?

Où le serveur Golang jsonrpc2 écoute-t-il ?

王林
王林avant
2024-02-08 21:27:28721parcourir

Golang jsonrpc2 服务器在哪里监听?

Où écoute le serveur Golang jsonrpc2 ? C'est un problème que de nombreux développeurs Golang rencontrent souvent lorsqu'ils utilisent le protocole jsonrpc2. Dans Golang, l'endroit où le serveur jsonrpc2 écoute dépend de la façon dont le code est implémenté. Une pratique courante consiste à demander au serveur d'écouter sur un port spécifique afin de recevoir les requêtes des clients. De plus, le serveur peut également être surveillé sur une interface réseau spécifique, telle que l'interface de bouclage locale (localhost) ou une adresse IP spécifiée. Afin de garantir que le serveur puisse écouter les requêtes et les traiter normalement, les développeurs doivent spécifier clairement l'emplacement d'écoute dans le code.

Contenu de la question

Je souhaite créer un simple serveur lsp en golang, voici le code que j'ai écrit jusqu'à présent :

package main

import (
    "context"
    "fmt"
    "os"
    "sync"

    "github.com/sourcegraph/jsonrpc2"
)

type lspserver struct {
    // the symmetric connection
    conn jsonrpc2.conn

    // check if the connection is available
    connmutex sync.mutex

    // shutdown
    shutdown bool
}

func newlspserver() *lspserver {
    return &lspserver{}
}

func (s *lspserver) initialize(ctx context.context) error {
    // to implement
    return nil
}

func (s *lspserver) handle(context.context, *jsonrpc2.conn, *jsonrpc2.request) (result interface{}, err error) {
    fmt.println("handling request...")
    // to implement
    return nil, nil
}

func (s *lspserver) serve(ctx context.context) {
    fmt.println("starting lsp server...")
    // what port is this server listening on?
    // it is listening on port 4389

    // create a new jsonrpc2 stream server
    handler := jsonrpc2.handlerwitherror(s.handle)

    // create a new jsonrpc2 stream server
    <-jsonrpc2.newconn(
        context.background(),
        jsonrpc2.newbufferedstream(os.stdin, jsonrpc2.vscodeobjectcodec{}),
        handler).disconnectnotify()
}

func main() {

    // create a new lsp server
    server := newlspserver()
    server.serve(context.background())

}

Cela fonctionne, mais je ne sais pas sur quel port il fonctionne, ni comment l'appeler via le client en général. Quelqu'un a-t-il une idée?

Je pensais que c'était le port 4389, mais ce n'est pas ça

J'utilise ce script pour tester :

import json
import requests

def rpc_call(url, method, args):
    headers = {'content-type': 'application/json'}
    payload = {
        "method": method,
        "params": [args],
        "jsonrpc": "2.0",
        "id": 1,
    }
    response = requests.post(url, data=json.dumps(payload), headers=headers).json()
    return response['result']

url = 'http://localhost:4389/'

emailArgs = {'To': '[email&#160;protected]','Subject': 'Hello', 'Content': 'Hi!!!'}
smsArgs = {'Number': '381641234567', 'Content': 'Sms!!!'}
print(rpc_call(url, 'email.SendEmail', emailArgs))
print(rpc_call(url, 'sms.SendSMS', smsArgs))

Je pense que c'est correct car j'ai obtenu ce client à partir d'une autre question de stackoverflow

Solution de contournement

Je comprends :

handlerwitherror(s.handle)

    // create a new jsonrpc2 stream server
    <-jsonrpc2.newconn(
        context.background(),
        jsonrpc2.newbufferedstream(os.stdin, jsonrpc2.vscodeobjectcodec{}),
        handler).disconnectnotify()
}

Cela signifie que votre code utilise json-rpc via une entrée et une sortie standard (stdin/stdout), au lieu de connexion via le réseau.
Lorsque vous utilisez l'argument de os.stdin 作为 jsonrpc2.newbufferedstream , vous spécifiez que l'entrée doit provenir de l'entrée standard du processus exécutant le serveur. et la réponse sera envoyée à la sortie standard.

Le serveur n’écoute donc sur aucun port réseau. Il interagit avec les données envoyées directement à ses entrées et sorties standard. Ceci est généralement utilisé pour la communication inter-processus, par exemple lorsque vous souhaitez qu'un processus appelle un processus serveur et reçoive une réponse.
Par exemple, voir « go : Communication bidirectionnelle avec un autre processus ? » ou davidelorenzoli/stdin-stdout-ipc.

Si vous souhaitez que le serveur json-rpc écoute sur un port réseau, vous devez utiliser le net package. Vous devrez également modifier le script client pour envoyer ses requêtes au bon port réseau au lieu d'envoyer une requête http à l'url.

package main

import (
    "context"
    "net"
    "log"
    "sync"

    "github.com/sourcegraph/jsonrpc2"
)

type LSPServer struct {
    // The symmetric connection
    conn jsonrpc2.Conn

    // Check if the connection is available
    connMutex sync.Mutex

    // shutdown
    shutdown bool
}

func NewLSPServer() *LSPServer {
    return &LSPServer{}
}

func (s *LSPServer) Initialize(ctx context.Context) error {
    // Initialize here if needed
    return nil
}

func (s *LSPServer) Handle(context.Context, *jsonrpc2.Conn, *jsonrpc2.Request) (result interface{}, err error) {
    fmt.Println("Handling request...")
    // Handle something
    return nil, nil
}

func (s *LSPServer) Serve(ctx context.Context) {
    fmt.Println("Starting LSP server...")
    
    // Listen on TCP port 4389 on all available unicast and
    // anycast IP addresses of the local system.
    l, err := net.Listen("tcp", "localhost:4389")
    if err != nil {
        log.Fatal(err)
    }
    defer l.Close()

    for {
        // Wait for a connection.
        conn, err := l.Accept()
        if err != nil {
            log.Fatal(err)
        }

        // Handle the connection in a new goroutine.
        go func(c net.Conn) {
            // Create a new jsonrpc2 stream server
            handler := jsonrpc2.HandlerWithError(s.Handle)
            <-jsonrpc2.NewConn(
                ctx,
                jsonrpc2.NewBufferedStream(c, jsonrpc2.VSCodeObjectCodec{}),
                handler).DisconnectNotify()
            c.Close()
        }(conn)
    }
}

func main() {
    // Create a new LSP server
    server := NewLSPServer()
    go server.Serve(context.Background()) // run Serve in a separate goroutine
    select {} // wait forever
}

Ceci est un exemple de base où la méthode serve crée un écouteur TCP écoutant sur le port 4389 de localhost. Il entre ensuite dans une boucle en attente d'une connexion, et lorsqu'il obtient une connexion, il démarre une nouvelle goroutine pour gérer la connexion à l'aide du serveur json-rpc.

Côté client, vous devez ouvrir une connexion TCP au serveur, écrire la requête json-rpc sur cette connexion, puis lire la réponse.

Vous ne pouvez pas utiliser la requests bibliothèque comme dans un script python, car elle est destinée aux requêtes http, pas aux connexions TCP brutes.
Vous devrez utiliser la socket bibliothèque en python, ou dans la langue de votre client, pour créer une connexion TCP et envoyer/recevoir des données via celle-ci.

Mais rappelez-vous, lsp (Language Server Protocol) fonctionne sur stdin/stdout et non sur les sockets réseau.
En effet, le serveur lsp est généralement démarré en tant que processus enfant par l'éditeur/IDE et communique directement via ces canaux. Ainsi, en fonction de votre cas d'utilisation, les méthodes brutes stdin/stdout peuvent être plus appropriées.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer