【问题标题】:Python-Micropython TCP sockets on w5100s-EVB-Picow5100s-EVB-Pico 上的 Python-Micropython TCP 套接字
【发布时间】:2022-09-29 00:25:58
【问题描述】:

我有一个W5100S-EVB-Pico,它基本上是一个带有以太网端口的 Pi Pico。我想通过 TCP 套接字连接向它发送命令。基本上我想使用这个板通过以太网控制硬件。

  • W5100 板应该是接受连接/命令的服务器。
  • 我打算用 Python 编写一个 GUI 来发送命令
  • 我正在运行this micropython version
  • Python 3.7 版

但这是现在的问题:下面的代码不断给我这个错误:\'操作系统错误:[Errno 107] ENOTCONN\'

  • EDIT_01:似乎我从客户端关闭连接太快了()
  • EDIT_02:我需要在关闭前得到服务器的某种确认吗?或者,有哪些可能的方式来实现这种通信?

谢谢阅读!

这是代码和对正在发生的事情的解释:

W5100-EVB-Pico 上的代码:

from machine import Pin, SPI
import network
import usocket as socket

# Only needed for static IP setup:
ip_address = \'192.168.1.20\'
subnet = \'255.255.255.0\'
gateway = \'192.168.1.1\'
dns = \'8.8.8.8\'

server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_port = 8080

# Init ethernet
def init_ethernet():
    spi = SPI(0, 2_000_000, mosi=Pin(19), miso=Pin(16), sck=Pin(18))
    nic = network.WIZNET5K(spi, Pin(17), Pin(20))
    # Static IP:
    # nic.ifconfig((ip_address, subnet, gateway, dns))
    # DHCP:
    nic.active(True)

    while not nic.isconnected():
        pass
    
    ip_address = nic.ifconfig()[0]
    subnet     = nic.ifconfig()[1]
    gateway    = nic.ifconfig()[2]
    dns        = nic.ifconfig()[3]

    print(\'Connected:\')
    print(\'IP        \', ip_address)
    print(\'Subnet    \', subnet)
    print(\'Gateway   \', gateway)
    print(\'DNS       \', dns)
    
    listen()
    
    
def listen():
    server_socket.bind((ip_address, socket_port))
    server_socket.listen(5)
    
    print(f\'Listening on {ip_address} port {socket_port}\')
    
    while True:
        print(\'>>>This should print once and it does\')
        print(\'>>>Waiting for connection\')
        client, address = server_socket.accept()
        print(f\'Client connected from: {address}\')
        client.close()


if __name__ == \"__main__\":
    init_ethernet()

运行时的输出是:

netif changed  192.168.1.20
Connected:
IP         192.168.1.20
Subnet     255.255.255.0
Gateway    192.168.1.1
DNS        192.168.1.150
Listening on 192.168.1.20 port 8080
>>>This should print once and it does
>>>Waiting for connection

我的 Python 代码:

import socket

local_IP = socket.gethostbyname(socket.gethostname())
port = 8080

server_ip = \'192.168.1.20\'
server_port = 8080
server_address = (server_ip, server_port)


def test_socket():

    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.connect(server_address)
        message = \'Hello from client\'
        s.sendall(bytes(message, encoding=\"utf-8\"))


if __name__ == \'__main__\':

    test_socket()

一旦我运行此代码,W5100 的输出就是:

...
>>>This should print once and it does
>>>Waiting for connection
Traceback (most recent call last):
  File \"<stdin>\", line 55, in <module>
  File \"<stdin>\", line 37, in init_ethernet
  File \"<stdin>\", line 49, in listen
OSError: [Errno 107] ENOTCONN

==============================================

  • EDIT_01: 我发现当我在这里添加 \'time.sleep(1)\' 时:
s.sendall(bytes(message, encoding=\"utf-8\"))
time.sleep(1)
s.close()

错误不会发生。我是否在 Python 端过早地关闭了套接字?

==============================================

  • EDIT_02:

我在服务器上更改了此代码:

    while True:
        print(\'>>>Waiting for connection\')
        client, address = server_socket.accept()
        print(f\'Client connected from: {address}\')
        data = client.recv(1024).decode()
        print(data)
        client.close()

这在客户端:

def test_socket():

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(server_address)
    message = \'This is a really long message of many bytes and can\\n\' \\
              \'even be some very long JSON data?\\n\' \\
              \'which is pretty awesome!\\n\' \\
              \'Man This is what I was after !!!\'
    s.sendall(bytes(message, encoding=\"utf-8\"))
    time.sleep(1)
    s.close()

但是, time.sleep(1) 不是要走的路:(

我想我应该在服务器确认后关闭套接字? 欢迎任何提示和提示, 谢谢!

  • 我发现当我在 \'s.sendall()\' 和 \'s.close()\' 之间添加 \'time.sleep(1)\' 时,它似乎(有点)工作?我的 Python 脚本是否过早关闭套接字?

标签: python sockets micropython


【解决方案1】:

好的,关键似乎是在通信中捕获错误。

此客户端代码按预期工作......现在。

import socket
import json

local_IP = socket.gethostbyname(socket.gethostname())
port = 8080

server_ip = '192.168.1.20'
server_port = 8080
server_address = (server_ip, server_port)

commands = [['A', 1, '1234567890_1234567890_1234567890'],
            ['B', 2, 'hello'],
            ['C', 3.7],
            ['D', 4]]

def test_socket():

    for c in commands:
        send(json.dumps(c))


def send(message):

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(server_address)

    s.sendall(bytes(message, encoding="utf-8"))

    try:
        received_data, addr = s.recvfrom(128)
        print(received_data, addr)
        print(received_data.decode('utf-8'))
    except socket.error as error:
        print(f'Socket error: {error.errno}')
    finally:
        pass


if __name__ == '__main__':

    test_socket()

【讨论】:

    猜你喜欢
    • 2021-07-01
    • 2022-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-09
    • 1970-01-01
    • 2021-09-10
    相关资源
    最近更新 更多