Skip to content

Commit e6c661e

Browse files
committed
allow reuse of tcp connection to send multiple request to one server
add writeToStream function for easy payload usage
1 parent ca092f4 commit e6c661e

File tree

3 files changed

+165
-8
lines changed

3 files changed

+165
-8
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* reuseConnection.ino
3+
*
4+
* Created on: 22.11.2015
5+
*
6+
*/
7+
8+
9+
#include <Arduino.h>
10+
11+
#include <ESP8266WiFi.h>
12+
#include <ESP8266WiFiMulti.h>
13+
14+
#include <ESP8266httpClient.h>
15+
16+
#define USE_SERIAL Serial1
17+
18+
ESP8266WiFiMulti WiFiMulti;
19+
20+
httpClient http;
21+
22+
void setup() {
23+
24+
USE_SERIAL.begin(115200);
25+
// USE_SERIAL.setDebugOutput(true);
26+
27+
USE_SERIAL.println();
28+
USE_SERIAL.println();
29+
USE_SERIAL.println();
30+
31+
for(uint8_t t = 4; t > 0; t--) {
32+
USE_SERIAL.printf("[SETUP] WAIT %d...\n", t);
33+
USE_SERIAL.flush();
34+
delay(1000);
35+
}
36+
37+
WiFiMulti.addAP("SSID", "PASSWORD");
38+
39+
40+
}
41+
42+
void loop() {
43+
// wait for WiFi connection
44+
if((WiFiMulti.run() == WL_CONNECTED)) {
45+
46+
http.begin("192.168.1.12", 80, "/test.html");
47+
48+
int httpCode = http.GET();
49+
if(httpCode) {
50+
USE_SERIAL.printf("[HTTP] GET... code: %d\n", httpCode);
51+
52+
// file found at server
53+
if(httpCode == 200) {
54+
http.writeToStream(&USE_SERIAL);
55+
}
56+
} else {
57+
USE_SERIAL.print("[HTTP] GET... faild, no connection or no HTTP server\n");
58+
}
59+
}
60+
61+
delay(1000);
62+
}
63+
64+
65+

libraries/ESP8266httpClient/src/ESP8266httpClient.cpp

Lines changed: 93 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,15 @@ httpClient::httpClient() {
3232
_tcp = NULL;
3333
_tcps = NULL;
3434

35+
_reuse = false;
36+
3537
_headerKeysCount = 0;
3638
_currentHeaders = NULL;
3739

3840
_returnCode = 0;
3941
_size = -1;
42+
_canReuse = false;
43+
4044
}
4145

4246
httpClient::~httpClient() {
@@ -52,6 +56,8 @@ httpClient::~httpClient() {
5256

5357
void httpClient::begin(const char *host, uint16_t port, const char * url, bool https, const char * httpsFingerprint) {
5458

59+
DEBUG_HTTPCLIENT("[HTTP-Client][begin] host: %s port:%d url: %s https: %d httpsFingerprint: %s\n", host, port, url, https, httpsFingerprint);
60+
5561
_host = host;
5662
_port = port;
5763
_url = url;
@@ -69,6 +75,19 @@ void httpClient::begin(String host, uint16_t port, String url, bool https, Strin
6975
begin(host.c_str(), port, url.c_str(), https, httpsFingerprint.c_str());
7076
}
7177

78+
/**
79+
* end
80+
* called after the payload is handeld
81+
*/
82+
void httpClient::end(void) {
83+
if((!_reuse || !_canReuse) && connected()) {
84+
DEBUG_HTTPCLIENT("[HTTP-Client][end] tcp stop \n");
85+
_tcp->stop();
86+
} else {
87+
DEBUG_HTTPCLIENT("[HTTP-Client][end] tcp keep open for reuse\n");
88+
}
89+
}
90+
7291
/**
7392
* connected
7493
* @return connected status
@@ -80,6 +99,16 @@ bool httpClient::connected() {
8099
return false;
81100
}
82101

102+
103+
/**
104+
* try to reuse the connection to the server
105+
* keep-alive
106+
* @param reuse bool
107+
*/
108+
void httpClient::setReuse(bool reuse) {
109+
_reuse = reuse;
110+
}
111+
83112
/**
84113
* send a GET request
85114
* @return http code
@@ -157,6 +186,53 @@ WiFiClient & httpClient::getStream(void) {
157186
// todo return error?
158187
}
159188

189+
/**
190+
* write all message body / payload to Stream
191+
* @param stream Stream *
192+
* @return bytes written
193+
*/
194+
int httpClient::writeToStream(Stream * stream) {
195+
196+
if(!stream) {
197+
return -1;
198+
}
199+
200+
// get lenght of document (is -1 when Server sends no Content-Length header)
201+
int len = _size;
202+
int bytesWritten = 0;
203+
204+
// create buffer for read
205+
uint8_t buff[1460] = { 0 };
206+
207+
// read all data from server
208+
while(connected() && (len > 0 || len == -1)) {
209+
210+
// get available data size
211+
size_t size = _tcp->available();
212+
213+
if(size) {
214+
int c = _tcp->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));
215+
216+
// write it to Stream
217+
bytesWritten += stream->write(buff, c);
218+
219+
if(len > 0) {
220+
len -= c;
221+
}
222+
}
223+
delay(1);
224+
}
225+
226+
DEBUG_HTTPCLIENT("[HTTP-Client] connection closed or file end.\n");
227+
228+
if(_size && _size != bytesWritten) {
229+
DEBUG_HTTPCLIENT("[HTTP-Client] bytesWritten %d and size %d missmatch!.\n", bytesWritten, _size);
230+
}
231+
232+
end();
233+
return bytesWritten;
234+
}
235+
160236
/**
161237
* adds Headder to the request
162238
* @param name
@@ -226,7 +302,7 @@ bool httpClient::hasHeader(const char* name) {
226302
bool httpClient::connect(void) {
227303

228304
if(connected()) {
229-
DEBUG_HTTPCLIENT("[HTTP-Client] connect. already connected, reuse!\n");
305+
DEBUG_HTTPCLIENT("[HTTP-Client] connect. already connected, try reuse!\n");
230306
return true;
231307
}
232308

@@ -235,7 +311,7 @@ bool httpClient::connect(void) {
235311
_tcps = new WiFiClientSecure();
236312
_tcp = _tcps;
237313
} else {
238-
DEBUG_HTTPCLIENT("[HTTP-Client] connect...\n");
314+
DEBUG_HTTPCLIENT("[HTTP-Client] connect http...\n");
239315
_tcp = new WiFiClient();
240316
}
241317

@@ -277,7 +353,14 @@ bool httpClient::sendHeader(const char * type) {
277353
String header = String(type) + " " + _url + " HTTP/1.1\r\n"
278354
"Host: " + _host + "\r\n"
279355
"User-Agent: ESP8266httpClient\r\n"
280-
"Connection: close\r\n" + _Headers + "\r\n";
356+
"Connection: ";
357+
358+
if(_reuse) {
359+
header += "keep-alive";
360+
} else {
361+
header += "close";
362+
}
363+
header += "\r\n" + _Headers + "\r\n";
281364

282365
return _tcp->write(header.c_str(), header.length());
283366
}
@@ -310,19 +393,22 @@ int httpClient::handleHeaderResponse() {
310393
_size = headerValue.toInt();
311394
}
312395

396+
if(headerName.equalsIgnoreCase("Connection")) {
397+
_canReuse = headerValue.equalsIgnoreCase("keep-alive");
398+
}
399+
313400
for(size_t i = 0; i < _headerKeysCount; i++) {
314-
if(_currentHeaders[i].key == headerName) {
401+
if(_currentHeaders[i].key.equalsIgnoreCase(headerName)) {
315402
_currentHeaders[i].value = headerValue;
316403
break;
317404
}
318405
}
319-
320406
}
321407

322408
if(headerLine == "") {
323-
DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] code: '%s'\n", String(_returnCode).c_str());
409+
DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] code: %d\n", _returnCode);
324410
if(_size) {
325-
DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] size: '%s'\n", String(_size).c_str());
411+
DEBUG_HTTPCLIENT("[HTTP-Client][handleHeaderResponse] size: %d\n", _size);
326412
}
327413
return _returnCode;
328414
}

libraries/ESP8266httpClient/src/ESP8266httpClient.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,12 @@ class httpClient {
4848

4949
void begin(const char *host, uint16_t port, const char * url = "/", bool https = false, const char * httpsFingerprint = "");
5050
void begin(String host, uint16_t port, String url = "/", bool https = false, String httpsFingerprint = "");
51+
void end(void);
5152

5253
bool connected(void);
5354

55+
void setReuse(bool reuse); /// keep-alive
56+
5457
/// request handling
5558
int GET();
5659
int POST(uint8_t * payload, size_t size);
@@ -71,6 +74,7 @@ class httpClient {
7174
int getSize(void);
7275

7376
WiFiClient & getStream(void);
77+
int writeToStream(Stream * stream);
7478

7579
protected:
7680

@@ -86,6 +90,8 @@ class httpClient {
8690
/// request handling
8791
String _host;
8892
uint16_t _port;
93+
bool _reuse;
94+
8995

9096
String _url;
9197
bool _https;
@@ -99,7 +105,7 @@ class httpClient {
99105

100106
int _returnCode;
101107
int _size;
102-
108+
bool _canReuse;
103109

104110
bool connect(void);
105111
bool sendHeader(const char * type);

0 commit comments

Comments
 (0)