1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-07-29 05:21:37 +03:00

Stream::send() (#6979)

This commit is contained in:
david gauchard
2021-03-15 01:36:20 +01:00
committed by GitHub
parent 4cc1472821
commit c720c0d9e8
48 changed files with 2136 additions and 650 deletions

View File

@ -0,0 +1,141 @@
/*
WiFiEcho - Echo server
released to public domain
*/
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <PolledTimeout.h>
#include <algorithm> // std::min
#ifndef STASSID
#define STASSID "your-ssid"
#define STAPSK "your-password"
#endif
constexpr int port = 23;
WiFiServer server(port);
WiFiClient client;
constexpr size_t sizes [] = { 0, 512, 384, 256, 128, 64, 16, 8, 4 };
constexpr uint32_t breathMs = 200;
esp8266::polledTimeout::oneShotFastMs enoughMs(breathMs);
esp8266::polledTimeout::periodicFastMs test(2000);
int t = 1; // test (1, 2 or 3, see below)
int s = 0; // sizes[] index
void setup() {
Serial.begin(115200);
Serial.println(ESP.getFullVersion());
WiFi.mode(WIFI_STA);
WiFi.begin(STASSID, STAPSK);
Serial.print("\nConnecting to ");
Serial.println(STASSID);
while (WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(500);
}
Serial.println();
Serial.print("connected, address=");
Serial.println(WiFi.localIP());
server.begin();
MDNS.begin("echo23");
Serial.printf("Ready!\n"
"- Use 'telnet/nc echo23.local %d' to try echo\n\n"
"- Use 'python3 echo-client.py' bandwidth meter to compare transfer APIs\n\n"
" and try typing 1, 1, 1, 2, 2, 2, 3, 3, 3 on console during transfers\n\n",
port);
}
void loop() {
MDNS.update();
static uint32_t tot = 0;
static uint32_t cnt = 0;
if (test && cnt) {
Serial.printf("measured-block-size=%u min-free-stack=%u", tot / cnt, ESP.getFreeContStack());
if (t == 2 && sizes[s]) {
Serial.printf(" (blocks: at most %d bytes)", sizes[s]);
}
if (t == 3 && sizes[s]) {
Serial.printf(" (blocks: exactly %d bytes)", sizes[s]);
}
if (t == 3 && !sizes[s]) {
Serial.printf(" (blocks: any size)");
}
Serial.printf("\n");
}
//check if there are any new clients
if (server.hasClient()) {
client = server.available();
Serial.println("New client");
}
if (Serial.available()) {
s = (s + 1) % (sizeof(sizes) / sizeof(sizes[0]));
switch (Serial.read()) {
case '1': if (t != 1) s = 0; t = 1; Serial.println("byte-by-byte (watch then press 2 or 3)"); break;
case '2': if (t != 2) s = 1; t = 2; Serial.printf("through buffer (watch then press 2 again, or 1 or 3)\n"); break;
case '3': if (t != 3) s = 0; t = 3; Serial.printf("direct access (watch then press 3 again, or 1 or 2)\n"); break;
}
tot = cnt = 0;
ESP.resetFreeContStack();
}
enoughMs.reset(breathMs);
if (t == 1) {
// byte by byte
while (client.available() && client.availableForWrite() && !enoughMs) {
// working char by char is not efficient
client.write(client.read());
cnt++;
tot += 1;
}
}
else if (t == 2) {
// block by block through a local buffer (2 copies)
while (client.available() && client.availableForWrite() && !enoughMs) {
size_t maxTo = std::min(client.available(), client.availableForWrite());
maxTo = std::min(maxTo, sizes[s]);
uint8_t buf[maxTo];
size_t tcp_got = client.read(buf, maxTo);
size_t tcp_sent = client.write(buf, tcp_got);
if (tcp_sent != maxTo) {
Serial.printf("len mismatch: available:%zd tcp-read:%zd serial-write:%zd\n", maxTo, tcp_got, tcp_sent);
}
tot += tcp_sent;
cnt++;
}
}
else if (t == 3) {
// stream to print, possibly with only one copy
if (sizes[s]) {
tot += client.sendSize(&client, sizes[s]);
} else {
tot += client.sendAll(&client);
}
cnt++;
switch (client.getLastSendReport()) {
case Stream::Report::Success: break;
case Stream::Report::TimedOut: Serial.println("Stream::send: timeout"); break;
case Stream::Report::ReadError: Serial.println("Stream::send: read error"); break;
case Stream::Report::WriteError: Serial.println("Stream::send: write error"); break;
case Stream::Report::ShortOperation: Serial.println("Stream::send: short transfer"); break;
}
}
}

View File

@ -0,0 +1,49 @@
#!/usr/bin/env python3
import os
import asyncio
# 512 bytes
message = bytearray(512);
bufsize=len(message)
print('message len=', bufsize)
global recv
recv = 0
async def tcp_echo_open (ip, port):
return await asyncio.open_connection(ip, port)
async def tcp_echo_sender(message, writer):
print('Writer started')
while True:
writer.write(message)
await writer.drain()
async def tcp_echo_receiver(message, reader):
global recv
print('Reader started')
while True:
data = ''.encode('utf8')
while len(data) < bufsize:
data += await reader.read(bufsize - len(data))
recv += len(data);
if data != message:
print('error')
async def tcp_stat():
global recv
dur = 0
loopsec = 2
while True:
last = recv
await asyncio.sleep(loopsec) # drifting
dur += loopsec
print('BW=', (recv - last) * 2 * 8 / 1024 / loopsec, 'Kibits/s avg=', recv * 2 * 8 / 1024 / dur)
loop = asyncio.get_event_loop()
reader, writer = loop.run_until_complete(tcp_echo_open('echo23.local', 23))
loop.create_task(tcp_echo_receiver(message, reader))
loop.create_task(tcp_echo_sender(message, writer))
loop.create_task(tcp_stat())
loop.run_forever()