#๐Ÿ”’ Can't exceed ~15000 requests to a raw socket server

22 messages ยท Page 1 of 1 (latest)

wispy lotus
#

I have a raspberry pi, and its too slow for running a http server and software pwm on its GPIO pins, so I made a custom "protocol" to send requests to it. The problem is that it uses raw socket, and the server side is made with asyncio, but with that I need to create a new socket connection every time I want to send a request. (I need to send ~165 requests per second). But after I exceed ~15000 requests, it starts saying Error: [WinError 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted.ห› and I can't figure out why...

hardy narwhalBOT
#

@wispy lotus

Python help channel opened

Remember to:

  • Ask your Python question, not if you can ask or if there's an expert who can help.
  • Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
  • Explain what you expect to happen and what actually happens.

:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.

wispy lotus
#

Can't exceed ~15000 requests to a raw socket server

odd kayak
#

You could reuse the socket?

#

And also are you closing the sockets when you're finished with them?

wispy lotus
# odd kayak You could reuse the socket?

how would I do that? I dont really know how to use raw sockets with asyncio
here is my current server code:

import asyncio

def parse_packet(data):
    return None, None, "OK"

async def handle_client(reader, writer):
    global counter
    try:

        transport = writer.get_extra_info('peername')

        client_ip = transport[0] if transport else None

        data = await reader.read(32768)

        rgb, json_dict, return_message = parse_packet(data)

        print(f"FROM {client_ip} --> {return_message}")

        counter += 1

        print(counter)

        writer.write(return_message.encode())
        await writer.drain()
    except Exception as e:
        print(f"Error: {e}")
    finally:
        writer.close()
        await writer.wait_closed()

async def main(host="0.0.0.0", port=8888):
    server = await asyncio.start_server(handle_client, host, port)interfaces, port 8888
    async with server:
        await server.serve_forever()

asyncio.run(main())
wispy lotus
#

And also I'm not using the socket module because as far as I know that would make me use a while True loop to check for packets and it messes up the pwm

odd kayak
#

Is your client closing connections?

#

You should probably use a while True loop in your handle_client, and send the length of the message followed by the message on the socket

#

Then you only need to open one socket from your windows machine

wispy lotus
#

yes, my client is closing connections. However I found why its saying the error...
I'm running out of local ports
I ran netstat -ano|findstr 8888
and the output was (after about a minute):

#

basically listing all the possible ephemeral ports on windows

odd kayak
#

Show your windows client source code?

wispy lotus
#
import json
import socket
import time
import re

SERVER_ADDRESS = '192.168.0.46'
SERVER_PORT = 8888

def is_rgb(s):
    pattern = re.compile(r'^(?:#)?[0-9A-Fa-f]{6}')
    return bool(pattern.match(s))

def rgb_to_bytes(rgb_string):
    if is_rgb(rgb_string):

        pairs = [rgb_string[i:i + 2] for i in range(0, len(rgb_string), 2)]
        bytes_list = [bytes.fromhex(pair) for pair in pairs]
        result = b''.join(bytes_list)
        return result
    else:
        raise ValueError(f"{rgb_string} is not a valid RGB code")

def send_data(rgb_data, json_dict):
    START_WORD = b"\x02\x7e\x30\x06"
    END_WORD = b"\x03\x7e\x30\x06"
    JSON_START_WORD = b"\x02json"
    JSON_END_WORD = b"\x03json"
    PADDING = b"\x00\x00\x00\x00\x00\x00"
    try:
        # Create a socket object
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # Connect to the server
        s.connect((SERVER_ADDRESS, SERVER_PORT))
        # Send data to the server
        s.send(START_WORD+PADDING+rgb_to_bytes(rgb_data)+JSON_START_WORD+json.dumps(json_dict).encode()+JSON_END_WORD+END_WORD)
        response = s.recv(1024)
        print(f"Response from server: {response.decode()}")
        s.close()
        time.sleep(0.005)
    except Exception as e:
        print(f"Error: {e}")

if __name__ == "__main__":
    st = time.time()
    counter = 0
    while time.time() < st + 120:
        counter += 1
        send_data("696969", {"test-json": "1234526789213456789123456789"})
        print(counter)

odd kayak
#

Why are you setting SO_REUSEADDR?

wispy lotus
#

I just copied that line hoping it would fix it, but it didnt

odd kayak
#

Use with socket.create_connection((SERVER_ADDRESS, SERVER_PORT)) as s:

wispy lotus
#

got the same error after 15000 requests

odd kayak
#

Show the updated code?

hardy narwhalBOT
#
Python help channel closed

This help channel has been closed and it's no longer possible to send messages here. If your question wasn't answered, feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.