I have the following client listed below to send request to my server using a custom protobuf message. How do I make this gevent friendly so I can make connection in parallel. Right now it seems the connection are made one by one in serie and it takes really long to create for example 50 users even if I specify to create ramp up the users by 50 every second.
https://www.gevent.org/intro.html#monkey-patching
import ssl
import struct
import sys
import time
import certifi
from client.kvgmprotobuf import PbUnion_pb2
from gevent import monkey
monkey.patch_socket()
import socket
class FleetSyncClient():
CERTIFICATE = 'mycertificate.pem'
def __init__(self, host):
self.hostname = host
self.ssock = None
def connect_terminal(self):
try:
# Set up the SSL context
context = ssl.create_default_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
context.load_cert_chain(certfile=self.CERTIFICATE)
# Open the SSL socket to the server
with socket.create_connection((self.hostname, 443)) as sock:
try:
self.ssock = context.wrap_socket(sock, server_hostname=self.hostname)
print(f"Connected to FarmCentre server: {self.hostname}")
return
except ssl.CertificateError as e:
print("Certificate validation error:", e)
print("Please check the server certifcate")
except ssl.SSLError as e:
print(f"Connection with server {self.hostname} failed: {e}")
except Exception as e:
print("An error occurred:", e)
except Exception as err:
print(f"Connection with server {self.hostname} failed unexpected {err=}, {type(err)=}")
print("Failed to connect to DAS server")
sys.exit(1)
def disconnect_terminal(self):
if self.ssock is not None:
try:
self.ssock.close()
except Exception as err:
print(f"Close connection failed{err=}, {type(err)=}")
sys.exit(1)
def abort(self, text):
print(f"###Error: {text}")
self.disconnect_terminal()
sys.exit(1)
def _send_message(self, data):
try:
# add data length 4 bytes MSB first
data = struct.pack('<I', len(data)) + data
# add two currently not used bytes
data = b'x00x00' + data
# add total length 4 bytes MSB first
data = struct.pack('<I', len(data)) + data
# print(binascii.hexlify(data))
####print(f"Sending {len(data)} bytes")
self.ssock.sendall(data)
except socket.error as e:
self.abort(f"Error sending data: {e}")
try:
# receive the response
self.ssock.settimeout(30)
header_bytes = self.ssock.recv(10)
# kvgmprotobuf message length is the last 4 bytes of the header
protobuf_msg_len = struct.unpack('<I', header_bytes[-4:])[0]
protobuf_response = b""
while len(protobuf_response) < protobuf_msg_len:
chunk = self.ssock.recv(1024)
protobuf_response += chunk
# print(f"Protobuf message: {binascii.hexlify(protobuf_response)}")
####print(f"Server response: {len(protobuf_response)} protobuf bytes")
return protobuf_response
except socket.error as e:
self.abort(f"Error receiving response: {e}")
# send kvgmprotobuf message to the server and return the server response kvgmprotobuf message
def send_protobuf_message(self, message):
####Logger.debug(f"sent message:n{message}")
response_data = self._send_message(message.SerializeToString())
# parse the serialized response bytes to a kvgmprotobuf message
response_msg = PbUnion_pb2.PbUnion()
response_msg.ParseFromString(response_data)
####print(f"{response_msg}")
return response_msg