Electron tcpclient.write issues

I’m trying to use the tcpclient to connect to a .net service to upload its data.

The process is working but i’m receiving duplicate values on my server side.

this is some of my code form my electron

            client.connect(server_host, server_port);
			Serial.printlnf("send_To_Server");
			Serial.println(command.length());
			char nP[command.length()] ; // was 512
			command.toCharArray(nP, command.length() + 1);


				Serial.println(nP);

				if (historyRecord == true){ // only record location messages...
					temp_sending_command = command; // temp store for the sending message
				}

				int client_written = client.write((unsigned char *)nP, sizeof(nP));
					nP[0];
        //  client.stop();
				if ( client_written< 0){
						Serial.printlnf("send_To_Server - ERROR");
						device_history_set(); // save to history file
						TCP_send = 0;
						state =SLEEP_WAIT_STATE;  /// so loop is ready for the return of data...
				}
				else{


						TCP_send = 1;
						sendCounter = sendCounter + 1;
					 	Serial.printlnf("send_To_Server - OK");
						state = PUBLISH_SERVER_REPLY; /// so loop is ready for the return of data...

				}

When i run the code on my electron and watch the outputs to the serial monitor i know that its only SENDING data once to my server, but my server is receiving the packets twice.

The length of my data ranges from 100 bytes to 1000’s depending upon various other processes.

Even when sending a simple 361 byte packet i receive it twice on my server.

I’m just wondering if i need to do anything else? I don;t want to close the connection on the electron device as i’m waiting for a reply from my server…

Could it be the reply is not fast enough - so the electron sends the data again? If so is there any way i can change this ??

Thanks

Your code looks OK (from what I can tell) but you haven’t shown the whole loop. It could be something else, other than what you have shown causing the problem. I see where you connect to the server with client.connect() and then send data with client.write(), but do you ever call client.stop()? I see that it has been commented out. I don’t know what the consequences are for calling client.connect() on your next loop without having called client.stop().

Also, you might want to investigate your .Net service and the components in between the client and server as well. (Disclaimer, my knowledge of TCP is not very deep but I get the basics.) Does your service acknowledge the packet or does it tell the client to resend? It may be that something in layer 1 or 2 is causing the packet to be resent and your service processes both the original and the resent packet.

Thanks
I close the tcpclient once i have received the OK from the server.

Normally on the server side I check for the IsCompleted flag from the asyn connection - but that is always returning true even when the tcpclient is sending a packet > 1024 bytes… So unless i can send more than 1024 bytes in a single write i’m a bit stuck.

I’m going to start a new mini project so i can concentrate on just the write code and see how that performs.

Thanks for the suggestions.

Check out this post by @rickkas7 which deals with sending large amount of data from a Photon to a server via TCPClient:

1 Like

thanks - i had seen this but i’ll have another read through.

On the Electron you can’t send more than 1024 bytes at a time. You’ll need to break it up into partial writes, the optimum size is actually 512 bytes per write.

Ideally, you should use a state machine like the link above, so that you don’t block loop for the entire send process. It’s best to return from loop and send another 512 bytes over several calls to loop.

4 Likes

I have done some testing and no matter how i do it ( either a loop with 512 bytes or sending the whole byte array) i only ever get the final bytes = 0 on my server if i send the client.stop();

int client_written = client.write((unsigned char *)nP, sizeof(nP)); //
Serial.println(client_written);

Now i want to leave the tcp connection open so i can send info back to the particle device... this is based upon what i just received.... So... how can I force / trick the particle tcpclient to send through the final packet... of 0 bytes.( which is what i receive on the client.stop() call)

Or do i have open the connection again??? which seems a bit silly.

I tried client.flush() and as it says on the documentation page - this did nothing!

I should also mention that i did get the data without the client.stop() - but as i do noth know the total length of the data i should be receiving..... i can't automatically continue in my server code until i receive the final call from the tcpclient....

I'm sure i'm going wrong somewhere or expecting something which does not exist

TCP does not work that way. There is no send zero bytes option in TCP. You can either send a packet of data, and the packet may include the FIN bit that marks it as the final packet. The FIN bit is sent after calling client.stop(). The FIN may be in a packet with data or without data, so I suppose technically there can be a zero length data in a packet, but only with a FIN.

In order to keep the connection open you either need to send the length (that’s what HTTP does with keep-alive mode), or you need to have some sort of terminator that marks the end of your transmission.

It’s not a limitation of the Electron, it’s a limitation of the underlying TCP protocol.

2 Likes

Hello

Thank you for that - I’ve only ever worked with TCP connections i suppose as end user where i’m just receiving stuff and not having to manage both sides. ( these could send more than 1024 bytes i believe so not had to work around this issue before )

I’ll add the packet length to the start of it - a simple solution… just wanted to check there was no predefined option.

I have just tried to send a second client.write(‘FIN’); to see if i receive this ( so i could add a FINISHED packet - but they don’t seem to come through in order as written in the code!

Thank you

TCP connections offer in-order reliable delivery so you shouldn’t be getting any data out of order.

But you do need to be careful because even if you send 512 bytes, for example, there’s no guarantee that the server will receive 512 bytes at once. Often they will but it’s not guaranteed. They could get 212 bytes, then later get another 300 bytes, in any quantities. In other words, the chunk size you write is not guaranteed to be the same that the server receives.

So even if you could write several K at a time with client.write() it still wouldn’t guarantee that the server would get all of the bytes at once.

1 Like

My server code manages the multiple packets it receives from the particle tcpclient and stitches them together.

I’ve tested with a sting 1500 chars long and I receive the data in 2 packets.

Now I know I have to include the length and terminator myself I should be fine.

Thanks

Also consider, the max size of a packet in transit is also governed by MTU settings of the network. Most home routers have 1500 as the default MTU. So if your packet is larger than 1500 bytes, it will most likely be broken into 2 packets by the network equipment. There is data overhead of about 40 bytes with the TCP packet so your payload of 1500 characters make the packet something like 1540 bytes (estimate). There’s a discussion about TCP overhead here: https://stackoverflow.com/questions/3613989/what-of-traffic-is-network-overhead-on-top-of-http-s-requests