You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何pylsp无响应?已启动TCP服务但请求无返回

问题描述

通过命令pylsp --verbose --tcp --host 127.0.0.1 --port 9999启动pylsp服务后,使用以下Python代码连接并发送initialize请求,但未收到任何响应:

import json
import socket

def send_request(request):
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
        sock.connect(('127.0.0.1', 9999))  # 假设LSP服务运行在本地9999端口
        request_str = json.dumps(request)
        # 发送请求长度,随后发送请求本身
        sock.sendall((len(request_str).to_bytes(4, byteorder='little')) + request_str.encode('utf-8'))

        # 读取响应长度(前4字节),然后读取响应
        response_length = int.from_bytes(sock.recv(4), byteorder='little')
        reponse = sock.recv(response_length).decode('utf-8')
        response = json.loads(reponse)

        return response

# 初始化LSP会话
initialize_request = {
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
        "processId": 12345,  # 任意进程ID
        "rootPath": "/path/to/my/repo",
        "capabilities": {},  # 为简化,发送空能力集
    }
}

response = send_request(definition_request)
print("Definition:", response)

通过netstat确认端口状态为LISTEN:

tcp4       0      0  127.0.0.1.9999         *.*                    LISTEN

尝试用telnet发送相同请求,依然无响应:

telnet 127.0.0.1 9999
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
        "processId": 12345,
        "rootPath": "/path/to/my/repo",
        "capabilities": {}
    }
}

请问遗漏了什么?


问题排查与解决

你遗漏了以下几个关键细节:

1. Python代码中的变量名错误

代码最后调用send_request(definition_request),但你定义的请求变量是initialize_request,这里存在笔误。这个错误会直接导致代码抛出NameError,根本没发送出正确的请求。

2. LSP TCP传输格式不符合规范

LSP(语言服务器协议)的TCP传输要求使用HTTP风格的Content-Length头部来标记消息边界,而不是直接发送二进制的长度前缀。你当前的代码直接发送4字节小端长度,这不符合LSP规范,pylsp无法识别这种格式,因此不会处理你的请求。

正确的LSP消息格式是:

Content-Length: <消息字节长度>\r\n
\r\n
<JSON格式的请求内容>

修正后的Python发送函数应该是这样:

def send_request(request):
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
        sock.connect(('127.0.0.1', 9999))
        request_str = json.dumps(request)
        # 构建符合LSP规范的消息头部
        header = f"Content-Length: {len(request_str)}\r\n\r\n"
        # 发送头部+请求内容
        sock.sendall(header.encode('utf-8') + request_str.encode('utf-8'))

        # 读取响应,先解析Content-Length
        response_header = b""
        while b"\r\n\r\n" not in response_header:
            response_header += sock.recv(1)
        # 提取Content-Length的值
        length_line = [line for line in response_header.decode('utf-8').split('\r\n') if line.startswith('Content-Length')][0]
        response_length = int(length_line.split(': ')[1])
        # 读取响应内容
        response_body = sock.recv(response_length).decode('utf-8')
        response = json.loads(response_body)

        return response

同时要修正变量名错误:

response = send_request(initialize_request)
print("Initialize Response:", response)

3. Telnet请求未遵循LSP格式

你用telnet发送请求时,只输入了JSON内容,但没有添加Content-Length头部,服务器无法确定消息何时结束,会一直等待完整的请求。正确的telnet发送方式应该是先输入头部,再空两行,然后输入JSON:

telnet 127.0.0.1 9999
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Content-Length: 178

{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
        "processId": 12345,
        "rootPath": "/path/to/my/repo",
        "capabilities": {}
    }
}

(注意:Content-Length的值要和你发送的JSON的字节长度一致,上面的178是示例值,需要根据实际JSON内容计算)

内容的提问来源于stack exchange,提问作者Exploring

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 06:35:16