added basic commands
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import shlex
|
||||
import socket
|
||||
import struct
|
||||
import argparse
|
||||
@@ -24,32 +25,61 @@ def recv_exact(sock: socket.socket, n: int) -> bytes:
|
||||
data += chunk
|
||||
return data
|
||||
|
||||
def send_frame(sock: socket.socket, payload: bytes) -> None:
|
||||
header = struct.pack('!I', len(payload))
|
||||
sock.sendall(header + payload)
|
||||
def send_command(sock: socket.socket, text: str) -> None:
|
||||
parts = shlex.split(text)
|
||||
if not parts:
|
||||
return
|
||||
|
||||
chunks = []
|
||||
|
||||
n_args = len(parts)
|
||||
chunks.append(struct.pack('!I', n_args))
|
||||
|
||||
for part in parts:
|
||||
part_bytes = part.encode()
|
||||
chunks.append(struct.pack('!I', len(part_bytes)))
|
||||
chunks.append(part_bytes)
|
||||
|
||||
payload = b''.join(chunks)
|
||||
|
||||
sock.sendall(struct.pack('!I', len(payload)) + payload)
|
||||
|
||||
def recv_frame(sock: socket.socket) -> bytes:
|
||||
def recv_response(sock: socket.socket) -> str:
|
||||
header = recv_exact(sock, 4)
|
||||
(length,) = struct.unpack('!I', header)
|
||||
if length > 10_000_000:
|
||||
raise ValueError('Message length is too long')
|
||||
return recv_exact(sock, length)
|
||||
|
||||
body = recv_exact(sock, length)
|
||||
if length < 4:
|
||||
raise ValueError("Response too short")
|
||||
|
||||
(status,) = struct.unpack('!I', body[:4])
|
||||
msg = body[4:]
|
||||
|
||||
if status == 0:
|
||||
if not msg:
|
||||
return "(ok)"
|
||||
return msg.decode("utf-8", errors='replace')
|
||||
elif status == 2:
|
||||
return "(nil)"
|
||||
else:
|
||||
return f"(err) {msg.decode('utf-8', errors='replace')}"
|
||||
|
||||
def main():
|
||||
print_logo()
|
||||
parser = argparse.ArgumentParser(description='NOT(Redis) client')
|
||||
parser.add_argument('-H', '--host', type=str, required=False, default='127.0.0.1', help='Server host')
|
||||
parser.add_argument('-P', '--port', type=int, required=False, default=6379, help='Server port')
|
||||
parser.add_argument('-M', '--message', type=str, required=False, default=None, help='Message to send (if not provided, starts interactive shell)')
|
||||
parser.add_argument('-M', '--message', type=str, required=False, default=None, help='Command to send (e.g. "set k v")')
|
||||
args = parser.parse_args()
|
||||
|
||||
try:
|
||||
with socket.create_connection((args.host, args.port)) as sock:
|
||||
if args.message:
|
||||
send_frame(sock, args.message.encode())
|
||||
response = recv_frame(sock)
|
||||
print('Message sent:', args.message)
|
||||
print('Server says:', response.decode("utf-8", errors='replace'))
|
||||
send_command(sock, args.message)
|
||||
response = recv_response(sock)
|
||||
print(response)
|
||||
else:
|
||||
print(f"Connected to {args.host}:{args.port}")
|
||||
print("Type 'quit' or 'exit' to leave.")
|
||||
@@ -66,9 +96,9 @@ def main():
|
||||
if cmd_line.lower() in ('quit', 'exit'):
|
||||
break
|
||||
|
||||
send_frame(sock, cmd_line.encode())
|
||||
response = recv_frame(sock)
|
||||
print(response.decode("utf-8", errors='replace'))
|
||||
send_command(sock, cmd_line)
|
||||
response = recv_response(sock)
|
||||
print(response)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\nType 'quit' or 'exit' to leave.")
|
||||
|
||||
Reference in New Issue
Block a user