sm09la:
@Shapeshifter- The "else" clause I was trying to reestablish a connection in case there was not one. As a result of not closing the connection, I assumed the following loop iteration the connection would still be opened.
Of course, this is a moot point since you are not doing it this way any more, and you are using a better method. But for the sake of learning, both for yourself and anyone else that may see this topic in the future, it's worth analyzing this. Not just for this particular problem, but as a general approach for figuring out future problems with other code. This is an object lifespan and reuse issue, and not specific to BridgeClient objects.
If the client object were defined inside the loop() function, then the client object would not stay open for the next iteration, because it would be destroyed at the end of the function when the client object goes out of scope. In that case, it would be constructed again at the top of the loop (assuming that the call to the constructor was at the top of the loop along with the object declaration.)
But the client object is declared and constructed outside of the loop() function, so it would indeed still be valid and potentially open at the top of the next loop() iteration. However, the first thing you do at the top of the loop is call server.accept() and assign the result to the client object. That call to server.accept() returns a new client object, which may or may not have a valid connection (most of the time it will NOT be connected, it will only be connected to the server if the server had just accepted an incoming connection.) Either way, the existing client object, which may have been connected from the previous loop iteration, is lost and overwritten by the new client object. If that overwritten client was open at the time, it will not have been properly closed, resulting in resource leakage, and eventually causing a failure to make connections or a crash of the system.
Now, if the server.accept() call returned a connected client, you process that connection, and then clean up the client by calling client.stop. This is just as it should be.
Later on in loop() you then tell the client object to connect to the server. This is no longer the client object that was around at the end of the prior loop, it is a new one that was assigned from the server.accept() call. That client may have had a connection and been stopped in the earlier code (no problem) or it could've been an unconnected client if there was no pending connection (still not a problem.) So it's valid to try and make a connection, and at the same time it really doesn't matter whether that prior object was still connected - it's gone, and your code doesn't try to reuse that open connection, it unconditionally attempts a new connection.
If you really want to try and re-use a connection that is active from a previous loop, you need to do a few things:
- Use two client objects so that one can be used for incoming connections without stomping on the outgoing connection
- Check whether the existing client object is connected (and make use of that connection) before attempting to open a new connection.
- Instead of using the "Connection: close" header, which may cause the remote server to unilaterally close the connection when done, use the "Connection: keep-alive" header to ask the remote server to keep the connection open and look for another incoming request.
- And you will probably also have to read (and discard?) the incoming data from the client or else the internal buffers may fill up and not be able to accept any more data from the server.
Yes, taking all of this into account, it's definitely easier to just call the Linux curl command! 8)