diff --git a/src/networking/__init__.py b/src/networking/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/networking/net_module.py b/src/networking/net_module.py new file mode 100644 index 0000000..0f47452 --- /dev/null +++ b/src/networking/net_module.py @@ -0,0 +1,130 @@ +import socket, threading + +class Networking: + """ + A class that contains common networking functions for both server and client. + """ + @staticmethod + def recv_any_size(sock): + """ + Receives data from the socket without knowing the size of the data. + + The sender must send the size of the data before sending the data. + """ + data_size = sock.recv(1024).decode() + sock.send("OK".encode()) + data = sock.recv(int(data_size)).decode() + return data + + @staticmethod + def send_any_size(sock, data): + """ + Sends data to the socket without knowing the size of the data. + + Sends the size of the data before sending the data. + """ + sock.send(str(len(data)).encode()) + response = sock.recv(1024).decode() + sock.send(data.encode()) +def recv_any_size(self, client): + """ + Receives data from the client without knowing the size of the data. + + Client must send the size of the data before sending the data. + """ + data_size = client.recv(1024).decode() + data = client.recv(int(data_size)).decode() + return data + +class Server: + """ + A basic server class that can be inherited to create a custom server. + + Contains some basic networking functions. + """ + def __init__(self, host = "127.0.0.1", port = 8080): + """ + Hosts a basic server on the specified host and port + """ + self.host = host + self.port = port + self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.server.bind((self.host, self.port)) + + def start(self, max_connections = 5): + """ + Starts the server and listens for *max_connections* connections, defaulted to 5 + """ + self.server.listen(max_connections) + while True: + client, addr = self.server.accept() + print(f"Connection from {addr}") + + # Start a new thread for the client + threading.Thread(target=self.handle_client, args=(client,)).start() + + def handle_client(self, client): + """ + Checks if the client sent "exit" and closes the connection if it did, else send the data back. + + Overwrite with your own implementation. + """ + while True: + data = self.recv(client) + if data == "exit": + break + self.send(client, data) + pass + + def send(self, client, data): + """ + Sends data to the client + """ + Networking.send_any_size(client, data) + + def recv(self, client): + """ + Receives data from the client + """ + return Networking.recv_any_size(client) + + def stop(self): + """ + Stops the server + """ + self.server.close() + + +class Client: + """ + A basic client class that can be inherited to create a custom client. + + Contains some basic networking functions. + """ + def __init__(self, host = "127.0.0.1", port = 8080): + """ + Connects to a server on the specified host and port + """ + self.host = host + self.port = port + self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.sock.connect((self.host, self.port)) + + def send(self, data): + """ + Sends data to the server + """ + Networking.send_any_size(self.sock, data) + + def recv(self): + """ + Receives data from the server + """ + return Networking.recv_any_size(self.sock) + + def close(self): + """ + Closes the connection + """ + Networking.send_any_size(self.sock, "exit") + self.sock.close() \ No newline at end of file diff --git a/src/test_networking.py b/src/test_networking.py new file mode 100644 index 0000000..7f6d6bc --- /dev/null +++ b/src/test_networking.py @@ -0,0 +1,24 @@ +from networking import net_module +import socket, threading + +class Test_server(net_module.Server): + def handle_client(self, client: socket.socket): + print(self.recv(client)) + self.send(client, "Hello World") + + print(self.recv(client)) + client.close() +class Test_client(net_module.Client): + def main(self): + + self.send("Hello World") + + print(self.recv()) + + self.close() + +server = Test_server() +threading.Thread(target=server.start, args=(1,)).start() +client = Test_client() + +client.main() \ No newline at end of file