sans-io模式,语言服务器协议实现
lsp的Python项目详细描述
sans-io模式下的语言服务器协议实现。它的灵感来自Sans-IO pattern。以及一些相关项目: -hyper-h2 -h11
因此,它可以很容易地与trio、asyncio或其他一些框架集成。
必需的python版本
python=3.6
功能
- 纯python实现
- 不与其他网站包相关
- 可以(应该)很容易地与诸如trio、asyncio等高级框架集成
如何安装
有两种方法可以安装lsp
- 通过pip安装(推荐)
pip install lsp
- 通过setup.py 安装
python setup.py install
基本用法示例
客户端
importsocketfromlspimportConnection,NEED_DATA,DataReceived,MessageEndsock=socket.socket()sock.connect(("localhost",10001))conn=Connection("client")answer=input("Send request?(y/n)")whileanswer=="y":# use connection send_json method to convert json object to bytesrequest_data=conn.send_json({"method":"didOpen"})# then we can send data to serversock.sendall(request_data)whileTrue:# and then we can get next_event of connection, it can indicate# that what should we do.event=conn.next_event()# we need to receive data from serverifeventisNEED_DATA:try:data=sock.recv(1024)exceptConnectionResetError:print('The server connection is closed, So I will leave:)')conn.close()sock.close()exit(0)else:print("return from sock.recv")conn.receive(data)# we have receive data from serverelifisinstance(event,DataReceived):print("Receive event, content:")print(event)elifisinstance(event,MessageEnd):print("Server sending data complete.")break# then we can call get_received_data() to extract out what we getheader,response_body=conn.get_received_data()print("Response header from server:")print(header)print("Response body from server:")print(response_body)answer=input("Send request?(y/n)")conn.go_next_circle()
服务器端
importsocketfromlspimportConnection,NEED_DATA,RequestReceived,DataReceived,MessageEndsock=socket.socket()sock.bind(("0.0.0.0",10001))sock.listen(1)client_sock,addr=sock.accept()print(f"get connection from {client_sock}")conn=Connection("server")try:whileTrue:whileTrue:# call next event to indicate what server socket should do.event=conn.next_event()# no data coming yet, so the return value is NEED_DATAifeventisNEED_DATA:data=client_sock.recv(1024)ifdata==b"":print("Client connection is closed, I will exit.")exit(0)conn.receive(data)# Request header is coming :)elifisinstance(event,RequestReceived):print("Receive request header")print(event.to_data())# Request data is coming :)elifisinstance(event,DataReceived):print("Receive request data")print(event.to_data())# client has send data completely.elifisinstance(event,MessageEnd):print("Data receive complete:)")break# so we can call con.get_received_data to fetch what client send.received_data=conn.get_received_data()print(f"Receiving data: {received_data}")# send response back to client.print(f"Sending response to client")data=conn.send_json({"Content":"I am received:)"})client_sock.sendall(data)print(f"For now, go to next circle")# then we need to call go_next_circle, to get another request from client.conn.go_next_circle()finally:sock.close()
有关更多用法示例,请签出examples/servers文件夹中的文件。
LSP中的主API
- 要发送JSON数据吗?您可以尝试
conn.send_json
。 - 想知道我们下一步该怎么做吗?你可以试试
conn.next_event
。 - 收到数据后,请不要忘记呼叫
conn.receive(data)
。 它将数据保存到内部缓冲区中,并可以驱动conn.next_event
方法返回其他事件。 - 当接收到
MessageEnd
事件时,我们可以调用conn.get_received_data
获取传入数据。
我们将从下一个活动中获得主要活动
客户
客户端将从下一个事件中获取以下值:
- 需要数据-这表示我们需要从服务器接收数据。
- responseReceived-客户端有接收响应头。
- datareceived-客户端已接收respone正文。
- messageend-从服务器接收数据完成。
服务器
服务器端将从下一个事件中获取以下值:
- 需要数据-这表示我们需要从客户端接收数据。
- requestReceived-客户端有发送请求头,我们接收它。
- datareceived-服务器从客户端接收响应正文。
- messageend-客户端发送请求完成。