Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add context manager for socket #196

Merged
merged 1 commit into from
Mar 19, 2024
Merged

Add context manager for socket #196

merged 1 commit into from
Mar 19, 2024

Conversation

anecdata
Copy link
Member

@anecdata anecdata commented Mar 16, 2024

Modeled after the WIZnet library (without the added complexities of its internal device and socket management).

Tested with Adafruit CircuitPython 9.0.0-rc.1 on 2024-03-14; Adafruit PyPortal with samd51j20, and:

  1. TCP socket client [HTTP] using adafruit_connection_manager
  2. UDP socket client using adafruit_connection_manager
  3. UDP socket server using adafruit_connection_manager
  4. UDP socket server using adafruit_connection_manager and asyncio: 8 tasks, each bind to a port, then each time a task receives a packet it exits the with and restarts that server. Client hits random ports at random intervals.

In each case, repeatedly executed the with block to check for closing and re-opening the sockets. Ran esp32spi debug mode (checking socket number) and enough iterations to demonstrate that sockets were properly closed (rather than using new sockets until they ran out). I haven't written a context manager before, and there may be subtleties I'm not thinking of with more complex uses, so I'd welcome any feedback with changes or other suggested tests.

Server code for 4th test...
import time
import os
import asyncio
import board
from digitalio import DigitalInOut
from adafruit_esp32spi import adafruit_esp32spi
import adafruit_connection_manager

PORTS = (5000, 5001, 5002, 5003, 5004, 5005, 5006, 5007,)

time.sleep(3)  # wait for serial

spi = board.SPI()
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)
radio = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset, debug=False)

print("Connecting to Wifi...", end=" ")
radio.connect({"ssid": os.getenv("WIFI_SSID"), "password": os.getenv("WIFI_PASSWORD")})
print(f'{radio.pretty_ip(radio.ip_address)}')

# get the socket pool from connection manager
socket = adafruit_connection_manager.get_radio_socketpool(radio)

async def udpserver(port):
    while True:
        with socket.socket(type=socket.SOCK_DGRAM) as s:
            print(f'Starting UDP server with sock={s._socknum} on {port=}')
            radio.start_server(port, s._socknum, conn_mode=radio.UDP_MODE)
            await asyncio.sleep(0)
            while True:
                numbytes_avail = radio.socket_available(s._socknum)
                if numbytes_avail:
                    print(f'Reading UDP socket with sock={s._socknum} on {port=} avail={numbytes_avail}', end=" ")
                    bytes_read = radio.socket_read(s._socknum, numbytes_avail)
                    print(f'{bytes_read}')
                    break
                await asyncio.sleep(0)

async def main():
    tasks = []
    for taskno in range(len(PORTS)):
        tasks.append(asyncio.create_task(udpserver(PORTS[taskno])))
    await asyncio.gather(*tasks)

asyncio.run(main())
Client code for 4th test...
import time
import random
import subprocess

host = '192.168.6.39'
while True:
    port = random.randint(5000, 5007)
    packet = f'UDP packet to {host}:{port}'
    print(f'Sending {packet}')
    ps = subprocess.Popen(('echo', f'{packet}'), stdout=subprocess.PIPE)
    output = subprocess.check_output(('nc', '-u', '-w', '1', f'{host}', f'{port}'), stdin=ps.stdout)
    ps.wait()
    time.sleep(random.uniform(0.1, 1.0))
Sample client output for 4th test...
Sending UDP packet to 192.168.6.39:5003
Sending UDP packet to 192.168.6.39:5003
Sending UDP packet to 192.168.6.39:5000
Sending UDP packet to 192.168.6.39:5005
Sending UDP packet to 192.168.6.39:5001
Sending UDP packet to 192.168.6.39:5002
Sending UDP packet to 192.168.6.39:5004
Sample server output for 4th test...
Connecting to Wifi... 192.168.6.39
Starting UDP server with sock=0 on port=5000
Starting UDP server with sock=1 on port=5001
Starting UDP server with sock=2 on port=5002
Starting UDP server with sock=3 on port=5003
Starting UDP server with sock=4 on port=5004
Starting UDP server with sock=5 on port=5005
Starting UDP server with sock=6 on port=5006
Starting UDP server with sock=7 on port=5007
Reading UDP socket with sock=3 on port=5003 avail=32 b'UDP packet to 192.168.6.39:5003\n'
Starting UDP server with sock=3 on port=5003
Reading UDP socket with sock=3 on port=5003 avail=32 b'UDP packet to 192.168.6.39:5003\n'
Starting UDP server with sock=3 on port=5003
Reading UDP socket with sock=0 on port=5000 avail=32 b'UDP packet to 192.168.6.39:5000\n'
Starting UDP server with sock=0 on port=5000
Reading UDP socket with sock=5 on port=5005 avail=32 b'UDP packet to 192.168.6.39:5005\n'
Starting UDP server with sock=5 on port=5005
Reading UDP socket with sock=1 on port=5001 avail=32 b'UDP packet to 192.168.6.39:5001\n'
Starting UDP server with sock=1 on port=5001
Reading UDP socket with sock=2 on port=5002 avail=32 b'UDP packet to 192.168.6.39:5002\n'
Starting UDP server with sock=2 on port=5002
Reading UDP socket with sock=4 on port=5004 avail=32 b'UDP packet to 192.168.6.39:5004\n'
Starting UDP server with sock=4 on port=5004

@anecdata anecdata linked an issue Mar 16, 2024 that may be closed by this pull request
@anecdata anecdata requested a review from a team March 17, 2024 13:31
@anecdata anecdata changed the title Add context manager Add context manager for socket Mar 17, 2024
Copy link
Contributor

@dhalbert dhalbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@dhalbert dhalbert merged commit 956d6a0 into adafruit:main Mar 19, 2024
1 check passed
adafruit-adabot added a commit to adafruit/Adafruit_CircuitPython_Bundle that referenced this pull request Mar 22, 2024
Updating https://github.com/adafruit/Adafruit_CircuitPython_AGS02MA to 1.0.8 from 1.0.7:
  > Merge pull request adafruit/Adafruit_CircuitPython_AGS02MA#4 from FoamyGuy/fix_readme

Updating https://github.com/adafruit/Adafruit_CircuitPython_DisplayIO_SSD1306 to 2.0.0 from 1.8.0:
  > Merge pull request adafruit/Adafruit_CircuitPython_DisplayIO_SSD1306#39 from makermelissa/master

Updating https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI to 7.1.0 from 7.0.1:
  > Merge pull request adafruit/Adafruit_CircuitPython_ESP32SPI#196 from anecdata/exit
  > Merge pull request adafruit/Adafruit_CircuitPython_ESP32SPI#192 from mMerlin/new-sample
  > Merge pull request adafruit/Adafruit_CircuitPython_ESP32SPI#193 from justmobilize/fix-readme-requirements

Updating https://github.com/adafruit/Adafruit_CircuitPython_FT5336 to 1.0.2 from 1.0.1:
  > Merge pull request adafruit/Adafruit_CircuitPython_FT5336#3 from adafruit/buttons_example

Updating https://github.com/adafruit/Adafruit_CircuitPython_GPS to 3.10.13 from 3.10.12:
  > Merge pull request adafruit/Adafruit_CircuitPython_GPS#102 from jkittner/minutes_fix

Updating https://github.com/adafruit/Adafruit_CircuitPython_HT16K33 to 4.6.9 from 4.6.7:
  > Merge pull request adafruit/Adafruit_CircuitPython_HT16K33#118 from adafruit/matrix_fill_color_swap
  > Merge pull request adafruit/Adafruit_CircuitPython_HT16K33#117 from DJDevon3/main

Updating https://github.com/adafruit/Adafruit_CircuitPython_LTR329_LTR303 to 3.0.6 from 3.0.5:
  > Merge pull request adafruit/Adafruit_CircuitPython_LTR329_LTR303#8 from FoamyGuy/fix_readme

Updating https://github.com/adafruit/Adafruit_CircuitPython_MAX31856 to 0.12.0 from 0.11.8:
  > Merge pull request adafruit/Adafruit_CircuitPython_MAX31856#28 from diegosolano/main

Updating https://github.com/adafruit/Adafruit_CircuitPython_MMC56x3 to 1.0.8 from 1.0.7:
  > Merge pull request adafruit/Adafruit_CircuitPython_MMC56x3#4 from FoamyGuy/fix_readme

Updating https://github.com/adafruit/Adafruit_CircuitPython_PCA9685 to 3.4.15 from 3.4.14:
  > Merge pull request adafruit/Adafruit_CircuitPython_PCA9685#55 from DJDevon3/WorkingBranch

Updating https://github.com/adafruit/Adafruit_CircuitPython_SI5351 to 1.4.4 from 1.4.3:
  > Merge pull request adafruit/Adafruit_CircuitPython_SI5351#31 from kamocat/main

Updating https://github.com/adafruit/Adafruit_CircuitPython_SSD1306 to 2.12.17 from 2.12.16:
  > Merge pull request adafruit/Adafruit_CircuitPython_SSD1306#85 from waynedyck/fix-pillow-10-errors

Updating https://github.com/adafruit/Adafruit_CircuitPython_TCA8418 to 1.0.11 from 1.0.10:
  > Merge pull request adafruit/Adafruit_CircuitPython_TCA8418#13 from FoamyGuy/fix_readme

Updating https://github.com/adafruit/Adafruit_CircuitPython_TSC2007 to 1.1.0 from 1.0.9:
  > Merge pull request adafruit/Adafruit_CircuitPython_TSC2007#6 from makermelissa/main

Updating https://github.com/adafruit/Adafruit_CircuitPython_TT21100 to 1.0.2 from 1.0.1:
  > Merge pull request adafruit/Adafruit_CircuitPython_TT21100#5 from FoamyGuy/fix_readme

Updating https://github.com/adafruit/Adafruit_CircuitPython_VL53L4CD to 1.2.2 from 1.2.0:
  > Merge pull request adafruit/Adafruit_CircuitPython_VL53L4CD#15 from FoamyGuy/fix_readme

Updating https://github.com/adafruit/Adafruit_CircuitPython_Wiznet5k to 5.0.9 from 5.0.7:
  > Merge pull request adafruit/Adafruit_CircuitPython_Wiznet5k#148 from pinkavaj/pi-fix-if
  > Merge pull request adafruit/Adafruit_CircuitPython_Wiznet5k#143 from us3r64/fix/socket-recv-timeout

Updating https://github.com/adafruit/Adafruit_CircuitPython_BitbangIO to 1.3.15 from 1.3.14:
  > Merge pull request adafruit/Adafruit_CircuitPython_BitbangIO#32 from kbsriram/i2c-clock-stretching
  > Merge pull request adafruit/Adafruit_CircuitPython_BitbangIO#31 from kbsriram/fix-phase

Updating https://github.com/adafruit/Adafruit_CircuitPython_HID to 6.1.1 from 6.1.0:
  > Merge pull request adafruit/Adafruit_CircuitPython_HID#125 from dhalbert/fix-class-docs

Updating https://github.com/adafruit/Adafruit_CircuitPython_NTP to 3.0.13 from 3.0.12:
  > Merge pull request adafruit/Adafruit_CircuitPython_NTP#31 from anecdata/cm_multi_radio

Updating https://github.com/adafruit/Adafruit_CircuitPython_PyCamera to 1.3.0 from 1.2.0:
  > Merge pull request adafruit/Adafruit_CircuitPython_PyCamera#33 from FoamyGuy/overlay_scale

Updating https://github.com/adafruit/Adafruit_CircuitPython_Requests to 3.2.2 from 3.0.1:
  > Merge pull request adafruit/Adafruit_CircuitPython_Requests#170 from DJDevon3/DJDevon3-TwitchAPI
  > Merge pull request adafruit/Adafruit_CircuitPython_Requests#169 from DJDevon3/DJDevon3-SteamAPI
  > Merge pull request adafruit/Adafruit_CircuitPython_Requests#166 from DJDevon3/GithubAPI
  > Merge pull request adafruit/Adafruit_CircuitPython_Requests#165 from DJDevon3/DJDevon3-PremiereLeagueAPI
  > Merge pull request adafruit/Adafruit_CircuitPython_Requests#160 from DJDevon3/main
  > Merge pull request adafruit/Adafruit_CircuitPython_Requests#164 from DJDevon3/DJDevon3-FitbitAPI
  > Merge pull request adafruit/Adafruit_CircuitPython_Requests#163 from DJDevon3/DJDevon3-DiscordAPI
  > Merge pull request adafruit/Adafruit_CircuitPython_Requests#162 from DJDevon3/DJDevon3-DiscordActive
  > Merge pull request adafruit/Adafruit_CircuitPython_Requests#161 from DJDevon3/MastodonBranch
  > Merge pull request adafruit/Adafruit_CircuitPython_Requests#159 from justmobilize/remove-response-close-read-all
  > Merge pull request adafruit/Adafruit_CircuitPython_Requests#156 from bablokb/main

Updating https://github.com/adafruit/Adafruit_CircuitPython_RGBLED to 1.2.0 from 1.1.19:
  > Merge pull request adafruit/Adafruit_CircuitPython_RGBLED#25 from BiffoBear/Error_check_colors

Updating https://github.com/adafruit/Adafruit_CircuitPython_RSA to 1.2.20 from 1.2.19:
  > Merge pull request adafruit/Adafruit_CircuitPython_RSA#40 from FoamyGuy/add_hashlib_req

Updating https://github.com/adafruit/Adafruit_CircuitPython_Bundle/circuitpython_library_list.md to NA from NA:
  > Updated download stats for the libraries
@anecdata anecdata deleted the exit branch March 25, 2024 18:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

No context manager for socket
2 participants