首頁  >  文章  >  後端開發  >  Golang jsonrpc2 伺服器在哪裡監聽?

Golang jsonrpc2 伺服器在哪裡監聽?

王林
王林轉載
2024-02-08 21:27:28721瀏覽

Golang jsonrpc2 服务器在哪里监听?

Golang jsonrpc2 伺服器在哪裡監聽?這是許多Golang開發者在使用jsonrpc2協定時經常遇到的問題。在Golang中,jsonrpc2伺服器監聽的位置取決於程式碼的實作方式。常見的做法是將伺服器監聽在特定的連接埠上,以便接收來自客戶端的請求。另外,也可以將伺服器監聽在特定的網路介面上,例如本機回環介面(localhost)或指定的IP位址上。為了確保伺服器能夠正常監聽請求並處理,開發者需要在程式碼中明確指定監聽的位置。

問題內容

我想在golang中建立一個簡單的lsp伺服器,到目前為止這是我寫的程式碼:

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

}

它可以運行,但我不知道它在哪個連接埠上運行,或者一般如何透過客戶端呼叫它。有人有什麼想法嗎?

我認為應該是連接埠4389,但不是那個

我正在使用此腳本進行測試:

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

我認為這是正確的,因為我從另一個 stackoverflow 問題中獲取了這個客戶

解決方法

我明白了:

handlerwitherror(s.handle)

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

這表示您的程式碼透過標準輸入和輸出(stdin/stdout)使用 json-rpc,而不是透過網路連接。
當您使用 os.stdin 作為 jsonrpc2.newbufferedstream 的參數時,您指定輸入應來自執行伺服器的進程的標準輸入。並且響應將被傳送到標準輸出。

因此,伺服器沒有偵聽任何網路連接埠。它與直接發送到其標準輸入和輸出的數據進行互動。這通常用於進程間通信,例如,當您希望一個進程調用伺服器進程並接收回應時。
例如,請參閱「go:與另一個程序進行雙向通訊?」或davidelorenzoli/stdin-stdout-ipc

如果您希望 json-rpc 伺服器偵聽網路端口,則需要使用 net 套件。您還需要修改客戶端腳本以將其請求發送到正確的網頁端口,而不是向 url 發送 http 請求。

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
}

這是一個基本範例,其中 serve 方法建立一個 tcp 偵聽器,偵聽本機的連接埠 4389。然後它進入一個等待連接的循環,當它獲得連接時,它會啟動一個新的 goroutine 來使用 json-rpc 伺服器處理該連接。

在客戶端,您需要打開到伺服器的 tcp 連接,將 json-rpc 請求寫入該連接,然後讀取回應。

您不能像在 python 腳本中使用 requests 函式庫,因為它用於 http 請求,不是原始 tcp 連線。
您將需要在 python 中使用 socket 函式庫,或在您客戶端的語言,以建立 tcp 連線並透過它傳送/接收資料。

但請記住,lsp(語言伺服器協定) 透過 stdin/stdout 運行而不是網路套接字。
這是因為 lsp 伺服器通常由編輯器/ide 作為子進程啟動,並透過這些通道直接通訊。因此,根據您的用例,原始的 stdin/stdout 方法可能更合適。

以上是Golang jsonrpc2 伺服器在哪裡監聽?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:stackoverflow.com。如有侵權,請聯絡admin@php.cn刪除