---
title: "CircuitPython Wiznet5k: PR #178 Socket Reliability Update"
url: "https://maker.wiznet.io/Grace_Koo/projects/match-core-socket-behaviour/"
markdown_url: "https://maker.wiznet.io/Grace_Koo/projects/match-core-socket-behaviour/md"
type: "UCC: User Created Content"
author: "adafruit"
author_url: "https://github.com/adafruit/Adafruit_CircuitPython_Wiznet5k/pull/178"
editor: "WIZnet"
editor_url: "https://maker.wiznet.io/"
original_author: "adafruit"
original_url: "https://github.com/adafruit/Adafruit_CircuitPython_Wiznet5k/pull/178"
published: "2026-02-06"
language: "en"
tags: ["CircuitPython"]
likes: 0
views: 1064
comments: 0
source: "WIZnet Makers (https://maker.wiznet.io/)"
---

# CircuitPython Wiznet5k: PR #178 Socket Reliability Update

> PR #178 aligns Wiznet5k sockets with CircuitPython core behavior, improving non-blocking/timeout reliability and consistency.

Original author: adafruit (source: https://github.com/adafruit/Adafruit_CircuitPython_Wiznet5k/pull/178)

## Components

- Software: **Adafruit Circuitpython** ([docs](https://docs.circuitpython.org/en/latest/README.html))

## Article

## [Update] Adafruit CircuitPython Wiznet5k Library: PR #178 Improves Core Socket Compatibility & Non-blocking Reliability

The **Adafruit_CircuitPython_Wiznet5k** library is a key networking driver for Python-based IoT projects built on WIZnet’s hardwired TCP/IP chips.
With **Pull Request #178**, the library’s socket behavior is aligned more closely with CircuitPython’s **core **`**socket**` semantics—especially around **non-blocking mode**, **timeouts**, **server **`**accept()**`** loops**, and **TCP close/disconnect sequences**.

---

## Key Improvements

### 1) `accept()` behavior matches core socket expectations

For server sockets, `accept()` now more clearly identifies cases where a connection is **not actually established yet**, such as:

- returned address is `0.0.0.0` or port is `0`, or

- socket status is not `ESTABLISHED`

Then it behaves like core socket patterns:

- **non-blocking (**`**timeout == 0**`**)** → raises `EAGAIN`

- **blocking with timeout** → raises `ETIMEDOUT` when time expires

- **blocking (or timeout not expired)** → continues waiting

Code excerpt from PR #178:

```plaintext
# accept() key logic (excerpt)
_, addr = self._interface.socket_accept(self._socknum)

# if any of the following conditions are true, we haven't accepted a connection if (
    addr[0] == "0.0.0.0"
    or addr[1] == 0
    or self._interface.socket_status(self._socknum)
    != wiznet5k.adafruit_wiznet5k.SNSR_SOCK_ESTABLISHED
):
    if self._timeout == 0:
        # non-blocking mode
        raise OSError(errno.EAGAIN)
    if self._timeout and 0 < self._timeout < ticks_diff(ticks_ms(), stamp) / 1000:
        # blocking mode with timeout
        raise OSError(errno.ETIMEDOUT)
    # blocking mode / timeout not expired
    continue
```

---

### 2) Clear `EAGAIN` handling in `recv_into()` for non-blocking reads

In non-blocking mode, if no data is available, `recv_into()` now raises `**EAGAIN**` (consistent with typical socket semantics).

```plaintext
# recv_into() non-blocking handling (excerpt) if self._timeout == 0:
    # non-blocking mode
    if num_read == 0:
        raise OSError(errno.EAGAIN)
    break
```

---

### 3) More consistent TCP shutdown behavior in `close()`

For TCP stream sockets, `close()` now calls `_disconnect()` first, then releases and closes the socket—improving consistency with core socket behavior.

```plaintext
# close() key logic (excerpt) if self._sock_type == SocketPool.SOCK_STREAM:
    self._disconnect()
self._interface.release_socket(self._socknum)
self._interface.socket_close(self._socknum)
self._socket_closed = True
```

---

## Why this matters

This merged PR aligns Wiznet5k socket behavior more closely with CircuitPython’s core `socket` semantics, including consistent handling of states and exceptions such as `EAGAIN` and `ETIMEDOUT`. In practice, this can **reduce ambiguity** when writing **non-blocking or timeout-driven loops**, making it easier to distinguish “no data yet” from “not connected/accepted yet” and helping application logic behave **more predictably**.

---

## Notes on “performance”

PR #178 is primarily about **behavioral alignment and clearer non-blocking/timeout semantics**, rather than a direct SPI throughput optimization. That said, in real applications, cleaner and more consistent state/exception handling can **help avoid ambiguous wait conditions** and may improve the overall stability and smoothness of long-running network workloads.

---

## ❓ FAQ

- **Q1. When was PR #178 merged?A**. It was **merged into **`**main**`** on Jan 23, 2026**.

- **Q2. Do I need to update my code?A. **Possibly—especially if your non-blocking logic previously relied on “silent 0-byte reads.” You may need to **catch **`**EAGAIN**`** and retry** for both `accept()` and `recv_into()`.

- **Q3. Does PR #178 make my projects faster automatically?A.** PR #178 is primarily a **behavioral alignment** change (matching core socket semantics), not a throughput/SPI optimization patch. Expect more consistent non-blocking/timeout behavior rather than guaranteed speed gains.

---

## Sources

- PR #178 (Match core socket behaviour): <https://github.com/adafruit/Adafruit_CircuitPython_Wiznet5k/pull/178><https://github.com/adafruit/Adafruit_CircuitPython_Wiznet5k/pull/178/changes?utm_source=chatgpt.com>

---

Source: https://maker.wiznet.io/Grace_Koo/projects/match-core-socket-behaviour/
