docs: adding tutorial 1
This commit is contained in:
parent
01585b6ec5
commit
a5727e3355
12 changed files with 764 additions and 0 deletions
0
package/examples/tutorials/chatapp/chatapp/__init__.py
Normal file
0
package/examples/tutorials/chatapp/chatapp/__init__.py
Normal file
63
package/examples/tutorials/chatapp/chatapp/client.py
Normal file
63
package/examples/tutorials/chatapp/chatapp/client.py
Normal file
|
@ -0,0 +1,63 @@
|
|||
import argparse
|
||||
import select
|
||||
import socket
|
||||
import sys
|
||||
import termios
|
||||
|
||||
DEFAULT_PORT: int = 9001
|
||||
READ_SIZE: int = 4096
|
||||
|
||||
|
||||
def prompt():
|
||||
sys.stdout.write(">> ")
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
class ChatClient:
|
||||
def __init__(self, address, port):
|
||||
self.address = address
|
||||
self.port = port
|
||||
|
||||
def run(self):
|
||||
server = socket.create_connection((self.address, self.port))
|
||||
sockname = server.getsockname()
|
||||
print(f"connected to server({self.address}:{self.port}) as client({sockname[0]}:{sockname[1]})")
|
||||
sockets = [sys.stdin, server]
|
||||
prompt()
|
||||
try:
|
||||
while True:
|
||||
read_sockets, write_socket, error_socket = select.select(sockets, [], [])
|
||||
for sock in read_sockets:
|
||||
if sock == server:
|
||||
message = server.recv(READ_SIZE)
|
||||
if not message:
|
||||
print("server closed")
|
||||
sys.exit(1)
|
||||
else:
|
||||
termios.tcflush(sys.stdin, termios.TCIOFLUSH)
|
||||
print("\x1b[2K\r", end="")
|
||||
print(message.decode().strip())
|
||||
prompt()
|
||||
else:
|
||||
message = sys.stdin.readline().strip()
|
||||
server.sendall(f"{message}\n".encode())
|
||||
prompt()
|
||||
except KeyboardInterrupt:
|
||||
print("client exiting")
|
||||
server.close()
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="chat app client",
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
)
|
||||
parser.add_argument("-a", "--address", help="address to listen on", required=True)
|
||||
parser.add_argument("-p", "--port", type=int, help="port to listen on", default=DEFAULT_PORT)
|
||||
args = parser.parse_args()
|
||||
client = ChatClient(args.address, args.port)
|
||||
client.run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
73
package/examples/tutorials/chatapp/chatapp/server.py
Normal file
73
package/examples/tutorials/chatapp/chatapp/server.py
Normal file
|
@ -0,0 +1,73 @@
|
|||
import argparse
|
||||
import select
|
||||
import socket
|
||||
|
||||
DEFAULT_ADDRESS: str = ""
|
||||
DEFAULT_PORT: int = 9001
|
||||
READ_SIZE: int = 4096
|
||||
|
||||
|
||||
class ChatServer:
|
||||
def __init__(self, address, port):
|
||||
self.address = address
|
||||
self.port = port
|
||||
self.sockets = []
|
||||
|
||||
def broadcast(self, ignore, message):
|
||||
for sock in self.sockets:
|
||||
if sock not in ignore:
|
||||
sock.sendall(message.encode())
|
||||
|
||||
def run(self):
|
||||
print(f"chat server listening on: {self.address}:{self.port}")
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server:
|
||||
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
server.bind((self.address, self.port))
|
||||
server.listen()
|
||||
self.sockets.append(server)
|
||||
try:
|
||||
while True:
|
||||
read_sockets, write_sockets, error_sockets = select.select(self.sockets, [], [])
|
||||
for sock in read_sockets:
|
||||
if sock == server:
|
||||
client_sock, addr = server.accept()
|
||||
self.sockets.append(client_sock)
|
||||
name = f"{addr[0]}:{addr[1]}"
|
||||
print(f"[server] {name} joining")
|
||||
self.broadcast({server, client_sock}, f"[server] {name} entered room\n")
|
||||
else:
|
||||
peer = sock.getpeername()
|
||||
name = f"{peer[0]}:{peer[1]}"
|
||||
try:
|
||||
data = sock.recv(READ_SIZE).decode().strip()
|
||||
if data:
|
||||
print(f"[{name}] {data}")
|
||||
self.broadcast({server, sock}, f"[{name}] {data}\n")
|
||||
else:
|
||||
print(f"[server] {name} leaving")
|
||||
self.broadcast({server, sock}, f"[server] {name} leaving\n")
|
||||
sock.close()
|
||||
self.sockets.remove(sock)
|
||||
except socket.error:
|
||||
print(f"[server] {name} leaving")
|
||||
self.broadcast({server, sock}, f"[server] {name} leaving\n")
|
||||
sock.close()
|
||||
self.sockets.remove(sock)
|
||||
except KeyboardInterrupt:
|
||||
print("closing server")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="chat app server",
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
)
|
||||
parser.add_argument("-a", "--address", help="address to listen on", default=DEFAULT_ADDRESS)
|
||||
parser.add_argument("-p", "--port", type=int, help="port to listen on", default=DEFAULT_PORT)
|
||||
args = parser.parse_args()
|
||||
server = ChatServer(args.address, args.port)
|
||||
server.run()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
26
package/examples/tutorials/chatapp/chatapp_service.py
Normal file
26
package/examples/tutorials/chatapp/chatapp_service.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
from typing import Dict, List
|
||||
|
||||
from core.config import Configuration
|
||||
from core.configservice.base import ConfigService, ConfigServiceMode, ShadowDir
|
||||
|
||||
|
||||
class ChatAppService(ConfigService):
|
||||
name: str = "ChatApp Server"
|
||||
group: str = "ChatApp"
|
||||
directories: List[str] = []
|
||||
files: List[str] = ["chatapp.sh"]
|
||||
executables: List[str] = []
|
||||
dependencies: List[str] = []
|
||||
startup: List[str] = [f"bash {files[0]}"]
|
||||
validate: List[str] = []
|
||||
shutdown: List[str] = []
|
||||
validation_mode: ConfigServiceMode = ConfigServiceMode.BLOCKING
|
||||
default_configs: List[Configuration] = []
|
||||
modes: Dict[str, Dict[str, str]] = {}
|
||||
shadow_directories: List[ShadowDir] = []
|
||||
|
||||
def get_text_template(self, _name: str) -> str:
|
||||
return """
|
||||
export PATH=$PATH:/usr/local/bin
|
||||
PYTHONUNBUFFERED=1 chatapp-server > chatapp.log 2>&1 &
|
||||
"""
|
17
package/examples/tutorials/chatapp/setup.py
Normal file
17
package/examples/tutorials/chatapp/setup.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
name="chatapp",
|
||||
version="0.1.0",
|
||||
packages=find_packages(),
|
||||
description="Chat App",
|
||||
entry_points={
|
||||
"console_scripts": [
|
||||
"chatapp-client = chatapp.client:main",
|
||||
"chatapp-server = chatapp.server:main",
|
||||
],
|
||||
},
|
||||
include_package_data=True,
|
||||
zip_safe=False,
|
||||
python_requires=">=3.6",
|
||||
)
|
Loading…
Add table
Add a link
Reference in a new issue