Initial commit

This commit is contained in:
Kayomn 2021-09-30 00:21:18 +01:00
commit a46242999b
5 changed files with 176 additions and 0 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Editors
.idea/
# Caches
__pycache__/
# Virtual environments
venv/

26
client.py Normal file
View File

@ -0,0 +1,26 @@
__author__ = "Kieran Osborne"
__version__ = "0.0.1"
__status__ = "Development"
if (__name__ == "__main__"):
import config
import socket as network
import message
def init() -> None:
address = (config.host, config.port)
print("Starting connection to", address)
with network.socket(network.AF_INET, network.SOCK_STREAM) as socket:
socket.setblocking(False)
socket.connect_ex(address)
while True:
message_body = input("Enter a message: ")
print("\n")
socket.send(message.serialize("Kayomn", message_body))
init()

6
config.py Normal file
View File

@ -0,0 +1,6 @@
__author__ = "Kieran Osborne"
__version__ = "0.0.1"
__status__ = "Development"
host = "127.0.0.1"
port = 12345

32
message.py Normal file
View File

@ -0,0 +1,32 @@
import sys
import json
import struct
class Message:
def __init__(self, author: str, body: str) -> None:
self.author = author
self.body = body
def serialize(self) -> bytes:
return serialize(self.author, self.body)
def deserialize(data: bytes) -> Message:
buffer_length = 2
header_length = struct.unpack(">H", data[:buffer_length])[0]
header = json.loads(data[buffer_length:header_length])
return Message(header["author"], header["encoded-body"])
def serialize(author: str, body: str) -> bytes:
encoding = sys.getdefaultencoding()
header_bytes = json.dumps({
"byteorder": sys.byteorder,
"author": author,
"body": encoding,
}).encode("utf-8")
return (struct.pack(">H", len(header_bytes)) + header_bytes)

104
server.py Normal file
View File

@ -0,0 +1,104 @@
__author__ = "Kieran Osborne"
__version__ = "0.0.1"
__status__ = "Development"
if (__name__ == "__main__"):
import config
import traceback
import socket as network
import selectors
import message
class User:
def __init__(self, user_socket: network.socket):
self.socket = user_socket
self.connection, self.address = user_socket.accept()
self.selector = selectors.DefaultSelector()
print("Accepted connection from", self.address)
self.connection.setblocking(False)
def close(self):
self.selector.close()
self.socket.close()
def read(self):
try:
# Should be ready to read
data = self.socket.recv(4096)
except BlockingIOError:
# Resource temporarily unavailable (errno EWOULDBLOCK)
pass
else:
if data:
print(message.deserialize(data))
else:
raise RuntimeError("Peer closed.")
def write(self):
pass
def run(self):
try:
while True:
events = self.selector.select(timeout=None)
for (key, mask) in events:
try:
if (mask & selectors.EVENT_READ):
self.read()
elif (mask & selectors.EVENT_WRITE):
self.write()
except Exception:
print(f"Exception raised on {self.address}: {traceback.format_exc()}"),
self.socket.close()
if not self.selector.get_map():
break
except KeyboardInterrupt:
print("caught keyboard interrupt, exiting")
finally:
self.selector.close()
def init():
address = (config.host, config.port)
selector = selectors.DefaultSelector()
with network.socket(network.AF_INET, network.SOCK_STREAM) as socket:
# Avoid bind() exception: OSError: [Errno 48] Address already in use
socket.setsockopt(network.SOL_SOCKET, network.SO_REUSEADDR, 1)
socket.bind(address)
socket.listen()
print("Listening on", address)
socket.setblocking(False)
selector.register(socket, selectors.EVENT_READ, data=None)
users = []
try:
while True:
events = selector.select(timeout=None)
for (key, mask) in events:
if key.data is None:
user = User(key.fileobj)
users.append(user)
user.run()
except KeyboardInterrupt:
print("Caught keyboard interrupt, exiting")
finally:
for user in users:
user.close()
selector.close()
init()