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

allow reuse of tcp connection to send multiple request to one server

add writeToStream function for easy payload usage
This commit is contained in:
Markus Sattler 2015-11-22 15:34:10 +01:00
parent ca092f4754
commit e6c661e7ba
3 changed files with 165 additions and 8 deletions

View File

@ -0,0 +1,65 @@
/**
* reuseConnection.ino
*
* Created on: 22.11.2015
*
*/
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266httpClient.h>
#define USE_SERIAL Serial1
ESP8266WiFiMulti WiFiMulti;
httpClient http;
void setup() {
USE_SERIAL.begin(115200);
// USE_SERIAL.setDebugOutput(true);
USE_SERIAL.println();
USE_SERIAL.println();
USE_SERIAL.println();
for(uint8_t t = 4; t > 0; t--) {
USE_SERIAL.printf("[SETUP] WAIT %d...\n", t);
USE_SERIAL.flush();
delay(1000);
}
WiFiMulti.addAP("SSID", "PASSWORD");
}
void loop() {
// wait for WiFi connection
if((WiFiMulti.run() == WL_CONNECTED)) {
http.begin("192.168.1.12", 80, "/test.html");
int httpCode = http.GET();
if(httpCode) {
USE_SERIAL.printf("[HTTP] GET... code: %d\n", httpCode);
// file found at server
if(httpCode == 200) {
http.writeToStream(&USE_SERIAL);
}
} else {
USE_SERIAL.print("[HTTP] GET... faild, no connection or no HTTP server\n");
}
}
delay(1000);
}

View File

@ -32,11 +32,15 @@ httpClient::httpClient() {
_tcp = NULL;
_tcps = NULL;
_reuse = false;
_headerKeysCount = 0;
_currentHeaders = NULL;
_returnCode = 0;
_size = -1;
_canReuse = false;
}
httpClient::~httpClient() {
@ -52,6 +56,8 @@ httpClient::~httpClient() {
void httpClient::begin(const char *host, uint16_t port, const char * url, bool https, const char * httpsFingerprint) {
DEBUG_HTTPCLIENT("[HTTP-Client][begin] host: %s port:%d url: %s https: %d httpsFingerprint: %s\n", host, port, url, https, httpsFingerprint);
_host = host;
_port = port;
_url = url;
@ -69,6 +75,19 @@ void httpClient::begin(String host, uint16_t port, String url, bool https, Strin
begin(host.c_str(), port, url.c_str(), https, httpsFingerprint.c_str());
}
/**
* end
* called after the payload is handeld
*/
void httpClient::end(void) {
if((!_reuse || !_canReuse) && connected()) {
DEBUG_HTTPCLIENT("[HTTP-Client][end] tcp stop \n");
_tcp->stop();
} else {
DEBUG_HTTPCLIENT("[HTTP-Client][end] tcp keep open for reuse\n");
}
}
/**
* connected
* @return connected status
@ -80,6 +99,16 @@ bool httpClient::connected() {
return false;
}
/**
* try to reuse the connection to the server
* keep-alive
* @param reuse bool
*/
void httpClient::setReuse(bool reuse) {
_reuse = reuse;
}
/**
* send a GET request
* @return http code
@ -157,6 +186,53 @@ WiFiClient & httpClient::getStream(void) {
// todo return error?
}
/**
* write all message body / payload to Stream
* @param stream Stream *
* @return bytes written
*/
int httpClient::writeToStream(Stream * stream) {
if(!stream) {
return -1;
}
// get lenght of document (is -1 when Server sends no Content-Length header)
int len = _size;
int bytesWritten = 0;
// create buffer for read
uint8_t buff[1460] = { 0 };
// read all data from server
while(connected() && (len > 0 || len == -1)) {
// get available data size
size_t size = _tcp->available();
if(size) {
int c = _tcp->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));
// write it to Stream
bytesWritten += stream->write(buff, c);
if(len > 0) {
len -= c;
}
}
delay(1);
}
DEBUG_HTTPCLIENT("[HTTP-Client] connection closed or file end.\n");
if(_size && _size != bytesWritten) {
DEBUG_HTTPCLIENT("[HTTP-Client] bytesWritten %d and size %d missmatch!.\n", bytesWritten, _size);
}
end();
return bytesWritten;
}
/**
* adds Headder to the request
* @param name
@ -226,7 +302,7 @@ bool httpClient::hasHeader(const char* name) {
bool httpClient::connect(void) {
if(connected()) {
DEBUG_HTTPCLIENT("[HTTP-Client] connect. already connected, reuse!\n");
DEBUG_HTTPCLIENT("[HTTP-Client] connect. already connected, try reuse!\n");
return true;
}
@ -235,7 +311,7 @@ bool httpClient::connect(void) {
_tcps = new WiFiClientSecure();
_tcp = _tcps;
} else {
DEBUG_HTTPCLIENT("[HTTP-Client] connect...\n");
DEBUG_HTTPCLIENT("[HTTP-Client] connect http...\n");
_tcp = new WiFiClient();
}
@ -277,7 +353,14 @@ bool httpClient::sendHeader(const char * type) {
String header = String(type) + " " + _url + " HTTP/1.1\r\n"
"Host: " + _host + "\r\n"
"User-Agent: ESP8266httpClient\r\n"
"Connection: close\r\n" + _Headers + "\r\n";
"Connection: ";
if(_reuse) {
header += "keep-alive";
} else {
header += "close";
}
header += "\r\n" + _Headers + "\r\n";
return _tcp->write(header.c_str(), header.length());
}
@ -310,19 +393,22 @@ int httpClient::handleHeaderResponse() {
_size = headerValue.toInt();
}
if(headerName.equalsIgnoreCase("Connection")) {
_canReuse = headerValue.equalsIgnoreCase("keep-alive");
}
for(size_t i = 0; i < _headerKeysCount; i++) {
if(_currentHeaders[i].key == headerName) {
if(_currentHeaders[i].key.equalsIgnoreCase(headerName)) {
_currentHeaders[i].value = headerValue;
break;
}
}
}
if(headerLine == "") {
DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] code: '%s'\n", String(_returnCode).c_str());
DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] code: %d\n", _returnCode);
if(_size) {
DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] size: '%s'\n", String(_size).c_str());
DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] size: %d\n", _size);
}
return _returnCode;
}

View File

@ -48,9 +48,12 @@ class httpClient {
void begin(const char *host, uint16_t port, const char * url = "/", bool https = false, const char * httpsFingerprint = "");
void begin(String host, uint16_t port, String url = "/", bool https = false, String httpsFingerprint = "");
void end(void);
bool connected(void);
void setReuse(bool reuse); /// keep-alive
/// request handling
int GET();
int POST(uint8_t * payload, size_t size);
@ -71,6 +74,7 @@ class httpClient {
int getSize(void);
WiFiClient & getStream(void);
int writeToStream(Stream * stream);
protected:
@ -86,6 +90,8 @@ class httpClient {
/// request handling
String _host;
uint16_t _port;
bool _reuse;
String _url;
bool _https;
@ -99,7 +105,7 @@ class httpClient {
int _returnCode;
int _size;
bool _canReuse;
bool connect(void);
bool sendHeader(const char * type);