Skip to content

lewoudar/gevent_socket

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

gevent socket

Just playing with gevent, socket, h2 and wsproto. May be later I will finalize it in a package..

The project contains:

  • a HTTP/2 server serving static files
  • a websocket client
  • a websocket abstract server

It you want to test it, follow the instructions below.

dependencies

To install the dependencies, you just need to run the following command:

pipenv install

If you don't know pipenv and how to install, look at the documentation here. It is a great tool for developing!

HTTP/2

To use the http/2 server, enter the h2_server the following command:

python init.py

the server will listen on port 8080 and will serve files from the path you provided as input or the current working directory if you haven't provided one

websocket client

Code sample

from typing import Any

from wsproto.events import AcceptConnection, CloseConnection

from websockets.client import Client


@Client.on_connect
def connect(client: Client, event: AcceptConnection) -> None:
    print('connection accepted')
    print(event)


@Client.on_disconnect
def disconnect(event: CloseConnection) -> None:
    print('connection closed')
    print(event)


@Client.on_ping
def ping(payload: bytes) -> None:
    print(payload)


@Client.on_pong
def pong(payload: bytes) -> None:
    print('pong message:', payload)


@Client.on_json_message
def handle_json_message(client: Client, payload: Any) -> None:
    print('json message:', payload)

@Client.on_text_message
def handle_text_message(client: Client, payload: str) -> None:
    print('text message:', payload)


@Client.on_binary_message
def handle_binary_message(client: Client, payload: bytearray) -> None:
    print('binary message:', payload)


with Client('ws://localhost:8080/foo') as client:
    client.ping()
    client.send_json({'hello': 'world'})
    client.send('my name is Kevin')
    client.send(b'just some bytes for testing purpose')

Notes:

  • If the server sends json data you will receive it on json handler and not text handler
  • I don't know why but ws_proto demands a path when giving the string connection so if you use a string connection like this one ws://localhost:8080 the client adds a default path called path.
  • If you run the sample above, you will notice that ping and pong handlers receive bytearray instead of bytes. Without any further research, I think that the response generated by wsproto returns bytearray. Normally it should not change how you handle the data because bytearray behaves exactly like bytes with some some additional improvements.
  • SSL is not supported.

websocket server

The actual server implemented is not a full server. You need to implement its abstract methods. An implementation example is at follows:

import sys
from typing import Any

from wsproto.events import Request

from websockets.server import BaseServer

class Server(BaseServer):
    def handle_request(self, request: Request) -> None:
        if request.subprotocols:  # this is only to demonstrate the usage of reject_request
            self.reject_request(reason='the server does not handle subprotocols')
            return
        self.accept_request()

    def handle_pong(self, data: bytes) -> None:
        print(data)

    def receive_bytes(self, data: bytes) -> None:
        print('receive bytes:', data)
        if b'ping me' in data:  # this is only to demonstrate the usage of ping
            self.ping(b'I ping you!')
            return
        self.send(data)

    def receive_text(self, data: str) -> None:
        print('receive text:', data)
        self.send(data)
        if 'bye' in data:  # this is only to demonstrate the usage of close_request
            self.close_request(1001, 'bye!')

    def receive_json(self, data: Any) -> None:
        print('receive json:', data)
        self.send_json(data)


server = None
try:
    hostname = sys.argv[1] if len(sys.argv) > 1 else '127.0.0.1'
    custom_port = int(sys.argv[2]) if len(sys.argv) > 2 else 8080
    print('running host', hostname, 'on port', custom_port)
    server = Server(hostname, custom_port)
    server.run()
except KeyboardInterrupt:
    server.close()

Notes:

  • Certificates can be supported by passing additional arguments to the run method. It must be the same arguments you pass to gevent.server.StreamServer
  • Data passed to handle_pong is bytearray. The same explanation as for the client applies here.

About

building some network stuff with gevent

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages