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; _tcp = NULL;
_tcps = NULL; _tcps = NULL;
_reuse = false;
_headerKeysCount = 0; _headerKeysCount = 0;
_currentHeaders = NULL; _currentHeaders = NULL;
_returnCode = 0; _returnCode = 0;
_size = -1; _size = -1;
_canReuse = false;
} }
httpClient::~httpClient() { 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) { 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; _host = host;
_port = port; _port = port;
_url = url; _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()); 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 * connected
* @return connected status * @return connected status
@ -80,6 +99,16 @@ bool httpClient::connected() {
return false; 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 * send a GET request
* @return http code * @return http code
@ -157,6 +186,53 @@ WiFiClient & httpClient::getStream(void) {
// todo return error? // 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 * adds Headder to the request
* @param name * @param name
@ -226,7 +302,7 @@ bool httpClient::hasHeader(const char* name) {
bool httpClient::connect(void) { bool httpClient::connect(void) {
if(connected()) { if(connected()) {
DEBUG_HTTPCLIENT("[HTTP-Client] connect. already connected, reuse!\n"); DEBUG_HTTPCLIENT("[HTTP-Client] connect. already connected, try reuse!\n");
return true; return true;
} }
@ -235,7 +311,7 @@ bool httpClient::connect(void) {
_tcps = new WiFiClientSecure(); _tcps = new WiFiClientSecure();
_tcp = _tcps; _tcp = _tcps;
} else { } else {
DEBUG_HTTPCLIENT("[HTTP-Client] connect...\n"); DEBUG_HTTPCLIENT("[HTTP-Client] connect http...\n");
_tcp = new WiFiClient(); _tcp = new WiFiClient();
} }
@ -277,7 +353,14 @@ bool httpClient::sendHeader(const char * type) {
String header = String(type) + " " + _url + " HTTP/1.1\r\n" String header = String(type) + " " + _url + " HTTP/1.1\r\n"
"Host: " + _host + "\r\n" "Host: " + _host + "\r\n"
"User-Agent: ESP8266httpClient\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()); return _tcp->write(header.c_str(), header.length());
} }
@ -310,19 +393,22 @@ int httpClient::handleHeaderResponse() {
_size = headerValue.toInt(); _size = headerValue.toInt();
} }
if(headerName.equalsIgnoreCase("Connection")) {
_canReuse = headerValue.equalsIgnoreCase("keep-alive");
}
for(size_t i = 0; i < _headerKeysCount; i++) { for(size_t i = 0; i < _headerKeysCount; i++) {
if(_currentHeaders[i].key == headerName) { if(_currentHeaders[i].key.equalsIgnoreCase(headerName)) {
_currentHeaders[i].value = headerValue; _currentHeaders[i].value = headerValue;
break; break;
} }
} }
} }
if(headerLine == "") { 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) { 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; 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(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 begin(String host, uint16_t port, String url = "/", bool https = false, String httpsFingerprint = "");
void end(void);
bool connected(void); bool connected(void);
void setReuse(bool reuse); /// keep-alive
/// request handling /// request handling
int GET(); int GET();
int POST(uint8_t * payload, size_t size); int POST(uint8_t * payload, size_t size);
@ -71,6 +74,7 @@ class httpClient {
int getSize(void); int getSize(void);
WiFiClient & getStream(void); WiFiClient & getStream(void);
int writeToStream(Stream * stream);
protected: protected:
@ -86,6 +90,8 @@ class httpClient {
/// request handling /// request handling
String _host; String _host;
uint16_t _port; uint16_t _port;
bool _reuse;
String _url; String _url;
bool _https; bool _https;
@ -99,7 +105,7 @@ class httpClient {
int _returnCode; int _returnCode;
int _size; int _size;
bool _canReuse;
bool connect(void); bool connect(void);
bool sendHeader(const char * type); bool sendHeader(const char * type);