-
Notifications
You must be signed in to change notification settings - Fork 1.3k
UDP native socket server reply not received by client #4445
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
Comments
CircuitPython ESP32-S2 UDP Socket Server example code: import wifi
import socketpool
import ipaddress
import time
from secrets import secrets
TIMEOUT = None
HOST = "" # see below; "127.0.0.1" and "localhost" don't work
PORT = 5000
MAXBUF = 256
# connect to wifi
print("Connecting to Wifi")
wifi.radio.connect(secrets["ssid"], secrets["password"])
pool = socketpool.SocketPool(wifi.radio)
print("Self IP", wifi.radio.ipv4_address)
HOST = str(wifi.radio.ipv4_address)
server_ipv4 = ipaddress.ip_address(pool.getaddrinfo(HOST, PORT)[0][4][0])
print("Server ping", server_ipv4, wifi.radio.ping(server_ipv4), "ms")
# make socket
print("Create UDP Server socket", (HOST, PORT))
s = pool.socket(pool.AF_INET, pool.SOCK_DGRAM)
s.settimeout(TIMEOUT)
s.bind((HOST, PORT))
buf = bytearray(MAXBUF)
while True:
size, addr = s.recvfrom_into(buf)
print("Received", buf[:size], size, "bytes from", addr)
size = s.sendto(buf[:size], addr)
print("Sent", buf[:size], size, "bytes to", addr) |
CPython UDP Socket Client example code: #!/usr/bin/env python3
import time
import socket
TIMEOUT = 5
HOST = "192.168.6.198" # edit as needed
PORT = 5000
MAXBUF = 256
buf = bytearray(MAXBUF)
while True:
print("Create UDP Client Socket")
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.settimeout(TIMEOUT)
size = s.sendto(b"Hello, world", (HOST, PORT))
print("Sent", size, "bytes")
size, addr = s.recvfrom_into(buf)
print("Received", buf[:size], size, "bytes from", addr)
s.close()
time.sleep(5) |
@hierophect seems something is odd about the client port number, TCP vs. UDP. I looked at the code but nothing jumped out at me.
Some sources mention optionally using |
Looks like the byte-order of the port number is the issue. i.e. 63312 is 0xF750 and 20727 is 0x50F7. Not sure which side isn't using network byte-order, though... |
Good catch! |
I think this may be the issue, in Socket.c A cursory glance at the lwip layer indicates that the port byte order is mostly managed there. However, Not flipping the port byte order in Also, const struct addrinfo hints = {
.ai_family = AF_INET,
.ai_socktype = SOCK_STREAM,
}; But changing it to SOCK_DGRAM didn't seem to change behavior. Not sure what that's really for. some time later... This works: The CPython UDP client above works with this CPython UDP server: #!/usr/bin/env python3
import time
import socket
HOST = ""
PORT = 5000
TIMEOUT = None
MAXBUF = 256
print("Create UDP Server Socket")
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.settimeout(TIMEOUT)
s.bind((HOST, PORT))
buf = bytearray(MAXBUF)
while True:
size, addr = s.recvfrom_into(buf)
print("Received", buf[:size], size, "bytes from", addr)
size = s.sendto(buf[:size], addr)
print("Sent", buf[:size], size, "bytes to", addr) |
Hypothesis No. 2: size, addr = s.recvfrom_into(buf)
print("Received", buf[:size], size, "bytes from", addr)
addr = (addr[0], htons(addr[1])) #test
size = s.sendto(buf[:size], addr)
print("Sent", buf[:size], size, "bytes to", addr) |
Closed by #4465 |
Firmware
Code/REPL
CircuitPython native UDP Server code & CPython UDP Client code are in the comments below.
Behavior
I've been testing cross-compatibility of CPython, CircuitPython ESP32SPI, and CircuitPython ESP32-S2 sockets, both TCP and UDP. All supported combinations work except CircuitPython ESP32-S2 UDP Server... none of the three types of clients receive the server's reply to the client-initiated message. It seems to be related to the port number.
TCP
For comparison, let's look first at the working TCP case. Notice in the CircuitPython TCP Server output below that the server accepts a connection from a remote (IP, PORT), receives data from the client, then echoes it back to the client.
CircuitPython TCP Server output:
TCP Client output (any of the three types):
Checking the
tcpdump
view of the transaction, we see that the client outgoing port (59337) does not match the CircuitPython-server-printed port (51687), BUT the dump shows the reply going back to the proper originating port. It works..UDP
Notice in the CircuitPython UDP Server output below that the server (waits until it) receives data from a remote (IP, PORT), then echoes it back to the client.
CircuitPython UDP Server output:
UDP Client output (any of the three types):
Checking the
tcpdump
view of the transaction, we see that the client outgoing port (63312) does not match the CircuitPython-server-printed port (20727). In this case the dump shows the reply going back to the CircuitPython-printed port (20727), BUT this does not work... the reply is never received by the client.I've tried longer timeouts, catching client exceptions and retrying, etc. None of the three types of clients receive the reply back from the native UDP server. All three types of clients do receive replies back from CPython UDP servers (ESP32SPI servers are not supported).
The text was updated successfully, but these errors were encountered: