Heim  >  Artikel  >  Backend-Entwicklung  >  Wo hört der Golang jsonrpc2-Server zu?

Wo hört der Golang jsonrpc2-Server zu?

王林
王林nach vorne
2024-02-08 21:27:28718Durchsuche

Golang jsonrpc2 服务器在哪里监听?

Wo hört der Golang jsonrpc2-Server zu? Dies ist ein Problem, auf das viele Golang-Entwickler häufig stoßen, wenn sie das jsonrpc2-Protokoll verwenden. Wo in Golang der jsonrpc2-Server lauscht, hängt davon ab, wie der Code implementiert wird. Eine gängige Praxis besteht darin, den Server einen bestimmten Port überwachen zu lassen, um Anfragen von Clients zu empfangen. Darüber hinaus kann der Server auch auf einer bestimmten Netzwerkschnittstelle überwacht werden, beispielsweise der lokalen Loopback-Schnittstelle (localhost) oder einer angegebenen IP-Adresse. Um sicherzustellen, dass der Server Anfragen abhören und normal verarbeiten kann, müssen Entwickler den Abhörort im Code klar angeben.

Frageninhalt

Ich möchte einen einfachen LSP-Server in Golang erstellen. Dies ist der Code, den ich bisher geschrieben habe:

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())

}

Es funktioniert, aber ich weiß nicht, auf welchem ​​Port es läuft, oder wie ich es generell über den Client aufrufen soll. Hat jemand irgendwelche Ideen?

Ich dachte, es wäre Port 4389, aber das ist es nicht

Ich verwende dieses Skript zum Testen:

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))

Ich denke, das ist richtig, weil ich diesen Client von einer anderen Stackoverflow-Frage erhalten habe

Workaround

Ich verstehe:

handlerwitherror(s.handle)

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

Das bedeutet, dass Ihr Code JSON-RPC über die Standardeingabe und -ausgabe (stdin/stdout) verwendet, anstatt eine Verbindung über das Netzwerk herzustellen.
Wenn Sie das Argument für os.stdin 作为 jsonrpc2.newbufferedstream verwenden, geben Sie an, dass die Eingabe von der Standardeingabe des Prozesses stammen soll, der den Server ausführt. und die Antwort wird an die Standardausgabe gesendet.

Der Server überwacht also keinen Netzwerkport. Es interagiert mit Daten, die direkt an seine Standardeingabe und -ausgabe gesendet werden. Dies wird normalerweise für die Kommunikation zwischen Prozessen verwendet, wenn Sie beispielsweise möchten, dass ein Prozess einen Serverprozess aufruft und eine Antwort erhält.
Siehe zum Beispiel „go: Zwei-Wege-Kommunikation mit einem anderen Prozess? “ oder davidelorenzoli/stdin-stdout-ipc.

Wenn Sie möchten, dass der JSON-RPC-Server einen Netzwerkport überwacht, müssen Sie das net-Paket verwenden. Sie müssen außerdem das Client-Skript ändern, um seine Anfragen an den richtigen Netzwerkport zu senden, anstatt eine http-Anfrage an die URL zu senden.

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
}

Dies ist ein einfaches Beispiel, bei dem die serve-Methode einen TCP-Listener erstellt, der Port 4389 von localhost überwacht. Anschließend tritt es in eine Schleife ein und wartet auf eine Verbindung. Wenn eine Verbindung hergestellt wird, startet es eine neue Goroutine, um die Verbindung mithilfe des JSON-RPC-Servers zu verarbeiten.

Auf der Clientseite müssen Sie eine TCP-Verbindung zum Server öffnen, die JSON-RPC-Anfrage an diese Verbindung schreiben und dann die Antwort lesen.

Sie können die requests Bibliothek nicht wie in einem Python-Skript verwenden, da sie für http-Anfragen und nicht für rohe TCP-Verbindungen gedacht ist.
Sie müssen die socket-Bibliothek in Python oder in der Sprache Ihres Kunden verwenden, um eine TCP-Verbindung herzustellen und darüber Daten zu senden/empfangen.

Aber denken Sie daran, lsp (Language Server Protocol) läuft über stdin/stdout und nicht über Netzwerk-Sockets.
Dies liegt daran, dass der LSP-Server normalerweise vom Editor/IDE als untergeordneter Prozess gestartet wird und direkt über diese Kanäle kommuniziert. Abhängig von Ihrem Anwendungsfall sind die rohen stdin/stdout-Methoden möglicherweise besser geeignet.

Das obige ist der detaillierte Inhalt vonWo hört der Golang jsonrpc2-Server zu?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen