Skip to content

Latest commit

 

History

History
187 lines (122 loc) · 5.95 KB

File metadata and controls

187 lines (122 loc) · 5.95 KB

Downloads

gruv-socks

This script provides a simple to use base server class and a Socket object that abstracts away the needed work to transport and recieve messages over TCP.

NOTE: The method used to reconstruct fragments does not work with protocols such as HTTP. This is designed to be used with simple self designed protocols.

Installation

pip install gruv_socks

Usage

Simple examples to show you how the library can be used.

Test Install

from gruv_socks.gruv_socks import server_test

print(server_test())
b"If you see this message, that means gruv_socks is working!"

Create Echo Server

This script will create a server that listens for data from clients, sends it back, then closes the connection. It will continue to run until stopped with Ctrl+C due to the blocking=True parameter in line 14. The deconstructor of the Socket object ensures it is properly closed, so you do not need to explicitly call it unless needed.

from gruv_socks.gruv_socks import ServerBase, SOCK_ERROR, SOCK_TIMEOUT

def callback(addr, sock):
    status, data = sock.read()  # receive read status, and received data

    # exit if read failed
    if status is False:
        if data == SOCK_ERROR:
            print("client error")

        elif data == SOCK_TIMEOUT:
            print("client timeout")

        return

    sock.write(data)  # send data back to client
    print(f"{addr[0]} said: {data.decode()}")

def main():
    server = ServerBase()
    server.start(callback, 5551, blocking=True)

if __name__ == "__main__":
    main()

Create Echo Client

This script will connect to the server running from the above script, send the text "Hello world!" disconnect, and then exit.

from gruv_socks.gruv_socks import Socket

def main():
	sock = Socket()
	
	sock.connect("localhost", 5551)
	sock.write("Hello world!")

	print(sock.read()[1])

	sock.disconnect()

if __name__ == "__main__":
	main()

Items Provided

A breakdown of the provided functions, objects, and variables.

Variable: SOCK_ERROR

Use to determine if a socket encountered an error.

Variable: SOCK_TIMEOUT

Use to determine if a socket encountered a time out.

Function: echo_callback(addr: tuple[str, int], sock: Socket)

Simple callback function to create an echo server with the ServerBase object.

Function: server_test()

Direct call function to test the BaseServer and Socket objects locally on the machine running it to ensure the library is working.

Object: Socket

Socket.timeout: int

Timeout (in seconds) to use for socket operations.

Socket.debug: bool

Decides if stack trace information is printed to console or not.

Socket.__sock: socket.socket

Holds the underlying socket object that communication is preformed with.

Socket.__init__(self, sock=None, timeout: int=60, debug: bool=False)

sock: Existing socket to use if supplied.

timeout: Time to wait (in seconds) for certain socket operations before stopping. I.e. connecting, reading data.

debug: If set to true, the stack trace will be printed to console upon errors for debugging.

Socket.__str__(self) -> str

def __str__(self) -> str:
    return f"gruv_socks.Socket(timeout={self.timeout}, debug={self.debug})"

Socket.__add__(self, x: bytes) -> bool

Shorthand for Socket.write()

def __add__(self, x: bytes) -> bool:
    return self.write(x)

Usage

from gruv_socks.gruv_socks import Socket

sock = Socket()
sock.connect("localhost", 5551)
sock + b"Hello world!"

Socket.connect(self, host: str, port: int) -> bool

Attempts to establish a connection to a given host. Returns bool dictating status.

host: Hostname/Address of host to connect to.

port: Port on the given host to connect to.

Socket.read(self, timeout_override: int=0) -> tuple[bool, bytes]

Attempts to read data from the socket object.

Returns a tuple containing a boolean dictating success status, and then the received data in byte string. If the status is False, then either gruv_socks.SOCK_ERROR, or gruv_socks.SOCK_TIMEOUT will be returned as the data.

timeout_override: If not 0, then overrides the set timeout for this singular read call.

Socket.write(self, data: bytes or str) -> bool

Attempts to write data to socket object, sending it to the connected host. Returns boolean dictating status.

data: Data to send to connected host.

Socket.disconnect(self)

Properly disconnects the socket object by shutting down READ/WRITE channels, and then closing the socket.

Socket.__del__(self)

Socket destructor, ensures the socket object properly closes before being destroyed.

Object:ServerBase

ServerBase.__init__(self, debug: bool=False)

Initializes the ServerBase object.

debug: Decides if stack trace information is printed to console or not.

ServerBase.__listen(self, callback)

Listens for incoming connections and hands them off to the callback function supplied.

ServerBase.start(self, callback, port: int, address: str="0.0.0.0", blocking: bool = False)

Makes the server listen with the given configuration.

The callback function is supplied 2 arguments. The first is a tuple of the remote IP, and the remote port. The second argument is the Socket object of the remote connection.

callback: Callback function to trigger upon new connections. callback( (host: str, port: int), Socket )

port: Port to listen on.

address: Address to listen on.

blocking: Boolean dictating wether or not this function should block, or spawn a thread to listen.

ServerBase.stop(self)

Stops the server by shutting down the listening socket and triggering the background thread to stop.

ServerBase.__del__(self)

Ensures the listening socket is properly closed, and the listening thread exits gracefully.