I’m trying to create a mini HTTP server, but I fail to make it work.
I only get the first request, and then ignores the client.stop(), running in an infinite loop.
I tried putting dalys, but I get strange behavior, hanging the core.
Do not know if I’m doing something wrong, or is there some bug.
Sorry for my English.
TCPServer server = TCPServer(80);
void setup()
{
server.begin();
Serial.begin(9600);
delay(1000);
Serial.println(Network.localIP());
Serial.println(Network.subnetMask());
Serial.println(Network.gatewayIP());
Serial.println(Network.SSID());
}
void loop()
{
TCPClient client = server.available();
if (client == true)
{
Serial.println("Client true");
if (client.connected()) {
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
client.print("Hello world ");
client.println("<br />");
}
Serial.println("Hello world ...");
if (client.connected()) {
Serial.println("Client conected");
client.flush();
client.stop();
Serial.println("Client Stop");
}
else
{
Serial.println("Client not connected");
}
}
}
What lengths of delays did you add? Perhaps try a few milliseconds, long enough to separate the messages, but not long enough to hang the Core.
When you say it runs in an ‘infinite loop’, what do you mean? If you put code to flash an LED in the loop, does the code continue to run, or does it hang?
The code above, does not close the client with client.stop(), and continues to enter (client == true)
When I make a request with curl, client should be true and enter the IF (client == true), and then with client.stop() would have to no longer enter. And that does not happen.
I think I have identified the problem: The implemention of TCPServer is actually giving you a clone of connected TCPClient. It acts kind of like the hidden original, but not quite well.
I have a proof of concept fix locally, but it uses pointers and I’m not sure if that is “Arduino-style”:
client->println("HTTP/1.1 200 OK");
One way to hide may be an extra helper class that is used instead of TCPClient (that extra class would only have the pointer and redirect commads to it), or maybe the client pointer can be included inside the TCPServer then these prints would be like:
I tried the example TCPServer, and also does strange things.
When I make a connection to port 23 and send one single character, make a loop that prints the same character.
Apparently client.read() function does not clear the buffer to read the next byte.
Also something strange happens with the connections, accepts the first connection, the second does not respond and accepts the third and fourth, then does not respond more connections. Forcing restart the core
Again sorry for my English
// EXAMPLE USAGE
// telnet defaults to port 23
TCPServer server = TCPServer(23);
void setup()
{
// start listening for clients
server.begin();
Serial.begin(9600);
delay(1000);
Serial.println(Network.localIP());
Serial.println(Network.subnetMask());
Serial.println(Network.gatewayIP());
Serial.println(Network.SSID());
}
void loop()
{
// if an incoming client connects, there will be bytes available to read:
TCPClient client = server.available();
if (client == true)
{
// read bytes from the incoming client and write them back
// to any clients connected to the server:
server.write(client.read());
}
}
Update to the TCPServer thread in general. I looked into this in response to a question from new user @Cretcheu.
The problem with the previous example code (which we should still get working) is that the call to TCPServer::available() constructs a new TCPClient when a currently connected client has no bytes available. I have posted new TCPServer example code that works with the current TCPServer implementation.
The most important change is a slightly different loop that only calls server.available() when needed rather than every time:
if (client.connected()) {
while (client.available()) {
server.write(client.read());
}
} else {
client = server.available();
}
I can flash this example from the web IDE, connect from my laptop using telnet, and get results echoed exactly as intended.
I gave the new server code a whirl and it’s still not working for me. Here is the code I’m using:
int LED = D1;
int TILT = A0;
int val = 0;
TCPServer server = TCPServer(4444);
TCPClient client;
void setup() {
// start listening for clients
server.begin();
Serial.begin(9600);
pinMode(LED, OUTPUT);
delay(1000);
Serial.println(Network.localIP());
Serial.println(Network.subnetMask());
Serial.println(Network.gatewayIP());
Serial.println(Network.SSID());
}
void loop() {
//get the current value of the tilt sensor
val = analogRead(TILT);
//use the debug LED to show things are still working
analogWrite(LED, val/16);
if(client.connected()) {
// echo all available bytes back to the client
while (client.available()) {
server.print(val);
}
}
else {
// if no client is yet connected, check for a new connection
client = server.available();
}
//fast fast!
delay(20);
}
I have an LED connected to the tilt sensor so that I know when it crashes (basically when a new connection comes in…).
Probably doesn’t help them I’m constantly getting the green flashing LED of death all the time as well
Now it does well, but not stop client on disconnect.
even with client.stop(); still client.connected() == true, and you can not connect any other client.
I tried also with client.flush(); without success
on the other hand, with this change, we can have 2 listening ports?
I strongly believe current TCPServer not working stable with latest code
(I am using Web build code)
I used the example from doc page to enable server on port 23. When I used the code as is, it work when connecting to Telnet.
But once combine with other part of the code, the system stop working.
Below is what I discover
If remove the line to wait for serial port Serial.available(), TCPServer will not able to connect client. However, when I put in a 15 seconds delay (about the time I start terminal), then it works.
Once TCPServer is called, all the Spark functions will not work (Spark.publish, Spark.variable, Spark.function) anymore.
I am still hoping for a solution or suggestion. Does anyone have some sample code which can be shared how to make TCPServer works together with Spark cloud functions ?
I want the spark to be a TCP server. When a client connects; the spark delivers a short HTML string and then disconnects.
This work 100% for the first connection but never for a second connection
int analogvalue = 0;
TCPServer myTCPserver = TCPServer(80);
TCPClient myTCPclient;
char szHTML[] = "sparkenv";
/*********************************************************************************************************
*********************************************************************************************************/
void setup() {
pinMode(PIN_LED_SPARK, OUTPUT);
pinMode(PIN_LED_IO, OUTPUT);
pinMode(PIN_POT, INPUT);
pinMode(PIN_SW, INPUT);
Serial1.begin(comm_uart_baud); //tx rx serial port
Serial1.println("Connect USB now");
Serial.begin(comm_usb_baud); //USB serial port
while(!Serial.available()) SPARK_WLAN_Loop();
Spark.disconnect();
myTCPserver.begin();
print_details();
Serial.println("Loop -");
Serial1.println("Loop -");
}
void loop() {
comms_usb_menu();
if (Serial1.available()){
char inByte = Serial1.read();
Serial1.print(inByte); //echo back out of port
}
digitalWrite(PIN_LED_SPARK, LOW);
if(myTCPclient.connected()){
Serial1.println("Con ");
if(myTCPclient.available()){
Serial1.print("\rClient avail...");
Serial1.print(Time.timeStr());
myTCPclient.write(szHTML);
delay(10);
myTCPclient.flush();
delay(100);
myTCPclient.stop();
Serial1.print("\rClient Stop!...");
Serial1.print(Time.timeStr());
}
}
else {
Serial1.print("\rNot Con");
myTCPclient = myTCPserver.available();
}
digitalWrite(PIN_LED_SPARK, HIGH);
}