Esp8266 - MDNS stop responding for some time after I send data - esp8266

My code is very simple, I use my esp8266 as a server which should wait for a client connection to read data from it and transmit it to the Arduino via the serial.
I use also the mDNS to detect the IP addresses of the ESP8266 inside the network and here's the code :
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <EEPROM.h>
.....
WiFiServer server(80);
void setup() {
Serial.begin(115200);
delay(10);
if (!MDNS.begin("Device 1")) { //
while (1) { delay(1000); }
}
MDNS.addService("SmartDimmerx2", "tcp", 80);
WiFi.mode(WIFI_STA);
delay(4000);
// Check if WiFi is already connected and if not,
if (WiFi.status() != WL_CONNECTED){
Serial.println("Disconnected");
ConnecStat_Toarduino = false;
}
else {
Serial.println("Connected");
ConnecStat_Toarduino = true;
}
// Start the server
server.begin();
}
void loop() {
MDNS.update();
if (WiFi.status() != WL_CONNECTED) {
Serial.println("Disconnected");
ConnecStat_Toarduino = false;
delay(100);
}
else if ((WiFi.status() == WL_CONNECTED) && (ConnecStat_Toarduino = false)) {
Serial.println("Connected");
ConnecStat_Toarduino = true;
}
if (Serial.available() > 0) {
String incomingChars = Serial.readStringUntil('\n');
if(incomingChars.indexOf("WPS") != -1) {
WPS_fnct();
}
}
// Check if a client has connected
WiFiClient client = server.available();
if (!client) {
time_cnx = millis();
return;
}
// Wait until the client sends some data
while (!client.available()) {
if ((millis() - time_cnx)>2000)
{return;}
delay(1);
}
// Read the first line of the request
String req = client.readStringUntil('\r');
client.flush();
client.stop();
// Match the request
int val;
if (req.indexOf("V=") != -1)
{
Serial.print(req.substring(2,5));
Serial.println(req.substring(7,11));
//Serial.println(char(req.substring(8,10).toInt()));
}
else {
client.stop();
return;
}
}
I use my phone app as a client and the code work perfectly, I scan for the “_SmartDimmerx2._tcp.local.” and the phone detect the esp with its IP addresses.
I was able to send data to the ESP and it receive it correctly and then send it back to arduino through serial,
The problem was after I send continuously some data to the ESP and then i try again to scan for the mDNS the ESP didn't respond. The ESP still not responding to the mDNS scan for like 30 seconds/1 minutes and after that it become discoverable again.
In the meantime when the mDNS is not responding the ESP still able to receive data from the phone and send it through the serial without any problem and display the correct data. So the esp is not bugged.
I feel like something is blocking the mDNS service when I send a lot of data from the phone. Did I made something wrong in my code ?
When the mDns is not responding I tried to scan with Zeroconf android app and it didn't respond too until after like one minute.

so i tried to activate the DEBUG in order to see what's wrong,
so i add #define DEBUG_ESP_MDNS_ERR in the beginning of the file and activate the debugging for serial inside the IDE and here's what i got.
1- when i first start the ESP i got these kind of lines that popping every like 2 seconds :
:urn 33
:urd 4, 33, 13
:urd 4, 33, 18
:urd 5, 33, 23
:urn 283
2- and every time i try to search for esp with my phone using the (ZeroconfResolver/mdns ) these line pop up, and my phone was able to find the esp8266
:urn 43
:urd 14, 43, 13
:urd 4, 43, 28
:urd 5, 43, 33
3- then when i send a series of data with my phone to the esp i got these kind of lines :
WS:ac
:rn 12
:ref 1
WS:av
:ref 2
:ur 2
:c0 1, 12
:ur 1
:close
WS:dis
:del
WS:ac
:rn 12
:ref 1
WS:av
:ref 2
:ur 2
:c0 1, 12
:ur 1
:close
WS:dis
:del
.........
so i use a slider in my phone and every time i change the value of it, it should send this value to the ESP
4.after sending some data i try again to search for the esp8266 using the (ZeroconfResolver/mdns ) and the esp didn't respond and the phone wasn't able to detect it, and here's what i got in the debug :
:urn 43
:urd 14, 43, 13
:urd 4, 43, 28
:urd 5, 43, 33
failed _reservefailed _reservefailed _reservefailed _reservefailed _reservefailed _reservefailed _reservefailed _reservefailed _reservefailed _reservefailed _reservefailed .........
so to get the esp discoverable again i can either restart the esp or i can wait for like 30 seconds to 2 minutes and the ESP will be discoverable again.
i search for this error 'failed _reserve' and i found it here inside the UdpContext.h
https://github.com/esp8266/Arduino/blob/461c922586564b8b8b1ece7e5591531b38dbfb87/libraries/ESP8266WiFi/src/include/UdpContext.h#L270
can anyone please explain me why this problem is triggered ? it's look like the tx buffer is full ? what should i do then ?
i'm sorry i'm a noob in network things , i'm only a electronic ing.
thx

Related

Soft wdt reset on ESP8266 when using Speed Sensor

I'm on my personal project to create a esp8266 module that can read several sensor from a vehicle and it can sends data over mqtt. so I have written the code where I try to reading the speed sensor its getting wdt reset and the esp8266 resetting again
so heres my code
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
lcd.init();
lcd.backlight();
pinMode(speedSensor,INPUT_PULLUP);
// attempt to connect to WiFi network:
Serial.print("Attempting to connect to WPA SSID: ");
Serial.println(ssid);
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
lcd.setCursor(0,0);
lcd.print("Connecting to");
lcd.setCursor(0,1);
lcd.print("the network");
Serial.print(".");
delay(5000);
}
lcd.clear();
Serial.println("You're connected to the network");
Serial.println();
lcd.setCursor(0,0);
lcd.print("Connected to");
lcd.setCursor(0,1);
lcd.print("the network");
delay(2000);
lcd.clear();
// attempt to connect to the MQTT broker:
Serial.print("Attempting to connect to the MQTT broker: ");
Serial.println(broker);
if (!mqttClient.connect(broker, port)) {
Serial.print("MQTT connection failed! Error code = ");
Serial.println(mqttClient.connectError());
while (1);
}
Serial.println("You're connected to the MQTT broker!");
Serial.println();
// subscribe to the topic and set callback function
mqttClient.onMessage(SwitchMotor);
mqttClient.subscribe(topicSwitchMotor);
lcd.setCursor(0,0);
lcd.print("Connected to");
lcd.setCursor(0,1);
lcd.print("the MQTT broker");
delay(2000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Fuel :");
lcd.setCursor(0,1);
lcd.print(" RPM :");
SPI.begin();
rfid.PCD_Init();
Serial.println("I am waiting for card...");
pinMode(pinRelay, OUTPUT);
digitalWrite(pinRelay, HIGH);
}
void loop() {
mqttClient.poll(); // check for incoming messages
FuelSensor(); // Fuel Sensor
SpeedMotor(); // Speed Sensor
StartMotor(); // Start Motor with RFID
}
void SpeedMotor(){
start_time=millis();
end_time=start_time+1000;
while(millis()<end_time){
yield();
if(digitalRead(speedSensor)){
steps=steps+1;
while(digitalRead(speedSensor));
}
}
// calculate the speed
temp=steps-steps_old;
steps_old=steps;
rps=(temp/20);
rpm=(rps*60);
lcd.setCursor(9,1);
lcd.print(rpm);
lcd.print(" ");
// publish the message
mqttClient.beginMessage(topicSpeedRpm);
mqttClient.print(rpm);
mqttClient.endMessage();
mqttClient.beginMessage(topicSpeedRps);
mqttClient.print(rps);
mqttClient.endMessage();
}
and this is the output from serial monitor
Attempting to connect to WPA SSID: cieciecie
...You're connected to the network
Attempting to connect to the MQTT broker: xx.xxx.xxx.xx
You're connected to the MQTT broker!
I am waiting for card...
--------------- CUT HERE FOR EXCEPTION DECODER ---------------
Soft WDT reset
>>>stack>>>
ctx: cont
sp: 3ffffde0 end: 3fffffc0 offset: 01a0
3fffff80: 3fffdad0 3ffee7bc 3ffee7c0 40201143
3fffff90: 3fffdad0 00000000 3ffeeaa8 402016e9
3fffffa0: 3fffdad0 00000000 3ffeeaa8 40205d5c
3fffffb0: feefeffe feefeffe 3ffe8600 40100e61
<<<stack<<<
--------------- CUT HERE FOR EXCEPTION DECODER ---------------
⸮⸮Attempting to connect to WPA SSID: cieciecie
...You're connected to the network
Attempting to connect to the MQTT broker: xx.xxx.xxx.xx
You're connected to the MQTT broker!
I am waiting for card...
--------------- CUT HERE FOR EXCEPTION DECODER ---------------
Soft WDT reset
it'll soft wdt reset all over again and again
I'd already try Stack ESP execption decoder and it given this results
ESP Exception decoder results
at the results its mentioning line 152 at speedMotor() function
void SpeedMotor(){
start_time=millis();
end_time=start_time+1000;
while(millis()<end_time){
yield(); // already use yield(); on while() loop
if(digitalRead(speedSensor)){ // line 152
steps=steps+1;
while(digitalRead(speedSensor));
}
}
// calculate the speed
temp=steps-steps_old;
steps_old=steps;
rps=(temp/20);
rpm=(rps*60);
lcd.setCursor(9,1);
lcd.print(rpm);
lcd.print(" ");
// publish the message
mqttClient.beginMessage(topicSpeedRpm);
mqttClient.print(rpm);
mqttClient.endMessage();
mqttClient.beginMessage(topicSpeedRps);
mqttClient.print(rps);
mqttClient.endMessage();
}
and i already try too from arduino forum https://forum.arduino.cc/t/solved-esp8266-millis-crash/636543
it says try using yield(); in the while() loop but its still given the soft wdt rest
i would like to have clear answer how to use the yield(); function properly so theres no more soft wdt resetting again
As per the comments the issue was in this section of code:
while(millis()<end_time){
yield(); // already use yield(); on while() loop
if(digitalRead(speedSensor)){ // line 152
steps=steps+1;
while(digitalRead(speedSensor));
}
}
The problem is that if digitalRead(speedSensor) returns true then a loop runs until digitalRead(speedSensor) returns false; this may run long enough to trigger the watchdog.
while(digitalRead(speedSensor));
One way of fixing this is to yield within the loop i.e.:
while(digitalRead(speedSensor)) {
yield();
}

Dart TCP socket concatenates all 'write' sync calls as a single packet

I'm trying to send multiple packets at once to a server, but the socket keeps "merging" all sync calls to write as a single call, I did a minimal reproducible example:
import 'dart:io';
void main() async {
// <Server-side> Create server in the local network at port <any available port>.
final ServerSocket server =
await ServerSocket.bind(InternetAddress.anyIPv4, 0);
server.listen((Socket client) {
int i = 1;
client.map(String.fromCharCodes).listen((String message) {
print('Got a new message (${i++}): $message');
});
});
// <Client-side> Connects to the server.
final Socket socket = await Socket.connect('localhost', server.port);
socket.write('Hi World');
socket.write('Hello World');
}
The result is:
> dart example.dart
> Got a new message (1): Hi WorldHello World
What I expect is:
> dart example.dart
> Got a new message (1): Hi World
> Got a new message (2): Hello World
Unfortunately dart.dev doesn't support dart:io library, so you need to run in your machine to see it working.
But in summary:
It creates a new tcp server at a random port.
Then creates a socket that connects to the previous created server.
The socket makes 2 synchronous calls to the write method.
The server only receives 1 call, which is the 2 messages concatenated.
Do we have some way to receive each synchronous write call in the server as separated packets instead buffering all sync calls into a single packet?
What I've already tried:
Using socket.setOption(SocketOption.tcpNoDelay, true); right after Socket.connect instantiation, this does modify the result:
final Socket socket = await Socket.connect('localhost', server.port);
socket.setOption(SocketOption.tcpNoDelay, true);
// ...
Using socket.add('Hi World'.codeUnits); instead of socket.write(...), also does not modify the result as expected, because write(...) seems to be just a short version add(...):
socket.add('Hi World'.codeUnits);
socket.add('Hello World'.codeUnits);
Side note:
Adding an async delay to avoid calling write synchronously:
socket.add('Hi World'.codeUnits);
await Future<void>.delayed(const Duration(milliseconds: 100));
socket.add('Hello World'.codeUnits);
make it works, but I am pretty sure this is not the right solution, and this isn't what I wanted.
Environment:
Dart SDK version: 2.18.4 (stable) (Tue Nov 1 15:15:07 2022 +0000) on "windows_x64"
This is a Dart-only environment, there is no Flutter attached to the workspace.
As Jeremy said:
Programmers coding directly to the TCP API have to implement this logic themselves (e.g. by prepending a fixed-length message-byte-count field to each of their application-level messages, and adding logic to the receiving program to parse these byte-count fields, read in that many additional bytes, and then present those bytes together to the next level of logic).
So I chose to:
Prefix each message with a - and suffix with ..
Use base64 to encode the real message to avoid conflict between the message and the previously defined separators.
And using this approach, I got this implementation:
// Send packets:
socket.write('-${base64Encode("Hi World".codeUnits)}.');
socket.write('-${base64Encode("Hello World".codeUnits)}.');
And to parse the packets:
// Cache the previous parsed packet data.
String parsed = '';
void _handleCompletePacket(String rawPacket) {
// Decode the original message from base64 using [base64Decode].
// And convert the [List<int>] to [String].
final String message = String.fromCharCodes(base64Decode(rawPacket));
print(message);
}
void _handleServerPacket(List<int> rawPacket) {
final String packet = String.fromCharCodes(rawPacket);
final String next = parsed + packet;
final List<String> items = <String>[];
final List<String> tokens = next.split('');
for (int i = 0; i < tokens.length; i++) {
final String char = tokens[i];
if (char == '-') {
if (items.isNotEmpty) {
// malformatted packet.
items.clear();
continue;
}
items.add('');
continue;
} else if (char == '.') {
if (items.isEmpty) {
// malformatted packet.
items.clear();
continue;
}
_handleCompletePacket(items.removeLast());
continue;
} else {
if (items.isEmpty) {
// malformatted packet.
items.clear();
continue;
}
items.last = items.last + char;
continue;
}
}
if (items.isNotEmpty) {
// the last data of this packet was left incomplete.
// cache it to complete with the next packet.
parsed = items.last;
}
}
client.listen(_handleServerPacket);
There are certainly more optimized solutions/approaches, but I got this just for chatting messages within [100-500] characters, so that's fine for now.

lwIP mqtt connection error on stm32f4 discovery

I am trying to use lwIP for a client, which sends data to mosquitto broker on stm32f407 discovery.
Mqtt application is implemented at lwIP. I just use them like that at main after initializing.
mqtt_client_t static_client;
Afterwards, with USART interrupt, I call
example_do_connect(&static_client); example_publish(&static_client,0);
Which calls those functions:
{
struct mqtt_connect_client_info_t ci;
err_t err;
/* Setup an empty client info structure */
memset(&ci, 0, sizeof(ci));
/* Minimal amount of information required is client identifier, so set it here */
ci.client_id = "lwip_test";
ci.client_user = NULL;
ci.client_pass = NULL;
/* Initiate client and connect to server, if this fails immediately an error code is returned
otherwise mqtt_connection_cb will be called with connection result after attempting
to establish a connection with the server.
For now MQTT version 3.1.1 is always used */
err = mqtt_client_connect(client, &serverIp, MQTT_PORT, mqtt_connection_cb, 0, &ci);
/* For now just print the result code if something goes wrong*/
if(err != ERR_OK) {
}
}
and
void example_publish(mqtt_client_t *client, void *arg)
{
const char *pub_payload= "stm32_test";
err_t err;
u8_t qos = 2; /* 0 1 or 2, see MQTT specification */
u8_t retain = 0; /* No don't retain such crappy payload... */
err = mqtt_publish(client, "pub_topic", pub_payload, strlen(pub_payload), qos, retain, mqtt_pub_request_cb, arg);
if(err != ERR_OK) {
// printf("Publish err: %d\n", err);
err = ERR_OK;
}
}
/* Called when publish is complete either with sucess or failure */
static void mqtt_pub_request_cb(void *arg, err_t result)
{
if(result != ERR_OK) {
// printf("Publish result: %d\n", result);
}
}
I am able to ping board, my IP adress has been assigned in main by using IP_ADDR4(&serverIp, 192,168,2,97);
I've used all needed functions like MX_LWIP_Init(), MX_LWIP_Process() and actually i am even able to implement a TCP client, which is working nice. So internet connection is well, but I guess, there is a point that i missed in mqttclient. Callbacks is also have done by Erik Anderssen's guide.
When i try to subscribe to board's IP by using mosquitto, Error: no connection could be made because the target actively refused it. If you notice some point that i have missed or have an idea, please let me know.
Any help will appreciated, thanks in advance.
I had a similar problem that the server refused the connection when QoS (quality of service) was set to 2, but the server needed it to be 0. Try changing the parameter qos in the line in the connection callback to either 0 or 1:
err = mqtt_subscribe(mqtt.client, "topic", qos, MqttApp_SubscribeRequestCallback, arg);
Same applies to the parameter qos in the publish function:
change u8_t qos = 2; to u8_t qos = 0; (or 1 - whatever your server requires)
Hope it helps. Cheers.

How is the ESP32 (DOIT DevKit) finding another host in the same LAN via mDNS?

I have a Raspberry Pi connected to my Wifi LAN that responds to mDNS as mqtt-broker.local.
I can find it on my laptop with this command:
$ avahi-resolve-host-name -4 mqtt-broker.local
mqtt-broker.local 192.168.XXX.YYY
I have an ESP32 DOIT DevKit device that can send messages to the Raspberry Pi via Wifi if I use the IP address 192.168.XXX.YYY, however I would like my ESP32 to resolve the host using mDNS.
I am not able to get the mDNS working, the code at the bottom prints:
Finding the mDNS details...
No services found...
Done finding the mDNS details...
What's wrong with this code?
What should I put as service in MDNS.queryService("mqtt-broker", "tcp")? I have tried even with service mqtt with no luck, however this shouldn't matter, the mDNS stuff should work regardless what's exposed from the Raspberry Pi (HTTP server, MQTT, FTP whatever...)
Checking here https://github.com/espressif/arduino-esp32/blob/master/libraries/ESPmDNS/src/ESPmDNS.h#L98 there is not that much information about this "service" and "proto", and I am not that much familiar with low-level C/C++, what are these things?
This is the code I am using:
// import the headers
#include <ESPmDNS.h>
void findMyPi() {
Serial.println("Finding the mDNS details...");
// make sure we are connected to the Wifi
while (WiFi.status() != WL_CONNECTED) {
delay(250);
Serial.println("Not yet connected to Wifi...");
}
if (!MDNS.begin("whatever_this_could_be_anything")) {
Serial.println("Error setting up MDNS responder!");
}
// what should I put in here as "service"?
int n = MDNS.queryService("mqtt-broker", "tcp");
if (n == 0) {
Serial.println("No services found...");
}
else {
for (int i = 0; i < n; ++i) {
// Print details for each service found
Serial.print(" ");
Serial.print(i + 1);
Serial.print(": ");
Serial.print(MDNS.hostname(i)); // "mqtt-broker" ??? How can I find it???
Serial.print(" (");
Serial.print(MDNS.IP(i));
Serial.print(":");
Serial.print(MDNS.port(i));
Serial.println(")");
}
}
Serial.println("Done finding the mDNS details...");
}
This function has been inspired by this example:
https://github.com/espressif/arduino-esp32/blob/master/libraries/ESPmDNS/examples/mDNS-SD_Extended/mDNS-SD_Extended.ino
Ended up using a different method from the class on that mDNS library provided by Espressif (ESPmDNS.h), a combination of:
IPAddress serverIp = MDNS.queryHost(mDnsHost);
while loop on this check serverIp.toString() == "0.0.0.0"
This is the code that glues up all together:
// on my laptop (Ubuntu) the equivalent command is: `avahi-resolve-host-name -4 mqtt-broker.local`
String findMDNS(String mDnsHost) {
// the input mDnsHost is e.g. "mqtt-broker" from "mqtt-broker.local"
Serial.println("Finding the mDNS details...");
// Need to make sure that we're connected to the wifi first
while (WiFi.status() != WL_CONNECTED) {
delay(250);
Serial.print(".");
}
if (!MDNS.begin("esp32whatever")) {
Serial.println("Error setting up MDNS responder!");
} else {
Serial.println("Finished intitializing the MDNS client...");
}
Serial.println("mDNS responder started");
IPAddress serverIp = MDNS.queryHost(mDnsHost);
while (serverIp.toString() == "0.0.0.0") {
Serial.println("Trying again to resolve mDNS");
delay(250);
serverIp = MDNS.queryHost(mDnsHost);
}
Serial.print("IP address of server: ");
Serial.println(serverIp.toString());
Serial.println("Done finding the mDNS details...");
return serverIp.toString();
}

Arduino WiFi shield post with header problems

I'm trying to do a post from the arduino wifi shield to my java servlet. The servlet functions with url get, and jquery post, but I can't sort the headers out in my arduino code. Any help will be greatly appreciated!
The server returns 200, but I'm not getting the payload "content" as value. I'm not exactly sure what I'm doing wrong but I'm pretty sure it's in how my headers are setup. I've spent the last two days trying to get it.
#include <SPI.h>
#include <WiFi.h>
char ssid[] = "jesussavesforjust19.95"; // your network SSID (name)
char pass[] = "********"; // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
IPAddress server(192,168,10,149); // numeric IP for Google (no DNS)
WiFiClient client;
void setup() {
Serial.begin(9600);
// attempt to connect to Wifi network:
while ( status != WL_CONNECTED) {
Serial.println("Attempting to connect to SSID: ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass);
// wait 10 seconds for connection:
delay(10000);
}
Serial.println("Connected to wifi");
printWifiStatus();
sendData("0600890876");
}
void loop() {
// if there's incoming data from the net connection.
// send it out the serial port. This is for debugging
// purposes only:
if (client.available()) {
char c = client.read();
Serial.println(c);
}
//String dataString = "060088765";
// if you're not connected, and ten seconds have passed since
// your last connection, then connect again and send data:
if(!client.connected())
{
Serial.println();
Serial.println("disconnecting.");
client.stop();
//sendData(dataString);
for(;;)
;
}
}
// this method makes a HTTP connection to the server:
void sendData(String thisData) {
// if there's a successful connection:
Serial.println("send data");
if (client.connect(server, 8080)) {
String content = "value=0600887654";
Serial.println(content);
Serial.println("connected");
client.println("POST /hos HTTP/1.1");
client.println("Host:localhost");
client.println("Connection:Keep-Alive");
client.println("Cache-Control:max-age=0");
client.println("Content-Type: application/x-www-form-urlencoded\n");
client.println("Content-Length: ");
client.println(content.length());
client.println("\n\n");
client.println(content);
}
else {
// if you couldn't make a connection:
Serial.println("form connection failed");
Serial.println();
Serial.println("disconnecting.");
client.stop();
}
}
void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.println("SSID: ");
Serial.println(WiFi.SSID());
// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.println("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.println("signal strength (RSSI):");
Serial.println(rssi);
Serial.println(" dBm");
}
Perhaps, some of your "Serial.println" and "client.println" commands should be "Serial.print" and "client.print" instead. For example:
client.print("Content-Length: ");
client.println(content.length());
would avoid adding a line break between the text and the number.
This is maybe more advice on an approach than an answer.
If I was doing something like this I would not start on the Arduino. The endless compile, download, run, look at print()'s would drive me crazy. I would fully prototype the client/server interaction in whatever you have at your fingertips, preferably something with a debugger. (Java, Python, PHP, VB, whatever you know that you can slap together)
Second, I would run Wireshark on the server so that I could see exactly what was being sent and responded.
Then I would port the same interaction over to the Arduino. Again inspect with Wireshark to confirm you are getting what you expected. If you send the same bytes, you should get the same response.
Even if you choose to implement straight on Arduino, consider having Wireshark to capture the actual network traffic.
With Wireshark, you might see that the Arduino println() is not sending the correct line end for the server.
Also, there is no guarantee that last println() is actually sent. The network stack implementation is free to buffer as it sees fit. You might need a flush(). A packet trace would show this.
With a packet capture you might find that time matters. In theory TCP is a stream and you should be able to send that POST data 1 character at a time in 1 packet and everything would work. But the Arduino might be so slow executing those println()'s by the server's standards that it times out. In such case you would see the server respond before the Arduino even finished sending.

Resources