Author Topic: Using TCP in the uTasker project  (Read 84025 times)

Offline aloft

  • Newbie
  • *
  • Posts: 18
    • View Profile
Re: Using TCP in the uTasker project
« Reply #45 on: June 30, 2010, 09:23:11 PM »
Thanks Mark. 

That helped - I'm now getting further.  I didn't realize the FTP server needed the "\r\n".

Thanks again,

TW

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: Using TCP in the uTasker project
« Reply #46 on: April 06, 2013, 12:31:31 AM »
Hi All

I would like to note that when the application receives the TCP_EVENT_REGENERATE is should repeat a lost frame and return APP_SENT_DATA.
If APP_ACCEPT is returned it will cause the TCP layer to consider this as an application error and close the connection.

Regards

Mark

Offline k64konfused

  • Newbie
  • *
  • Posts: 25
    • View Profile
Re: Using TCP in the uTasker project
« Reply #47 on: October 10, 2014, 06:28:52 AM »
Hi Mark, although this is related to my "newbie" thread, I wanted to post here since it's related to TCP.  I am not an experienced network programmer by any means.  Most of the code I have written on Windows to program sockets uses really high level .NET libraries and aren't ever used in production code.

In order to get myself familiarized with sockets on uTasker, I felt that a reasonable starting point would be to leverage the simulator and modify the fnMyFirstTask() function from the getting started guide.  Here's what I ended up with:

Code: [Select]
extern void fnMyFirstTask(TTASKTABLE *ptrTaskTable)
{
static unsigned char ucCounter = 0;

/*
fnDebugMsg("Hello, World!  Test number ");
fnDebugDec(ucCounter++, 0);
fnDebugMsg("\r\n");
*/

static unsigned char ucRemoteIP[IPV4_LENGTH] = {192,168,0,112};
unsigned char data[MIN_TCP_HLEN + 4];
//memset( data, 0, 1024);

USOCKET test_client_socket = fnGetTCP_Socket(TOS_MINIMISE_DELAY, TCP_DEFAULT_TIMEOUT, fnTestTcpServerConnect);
if (test_client_socket >= 0) {
USOCKET ret;
    if( (ret = fnTCP_Connect(test_client_socket, ucRemoteIP, 50000, 0, 0)) > 0) {
fnDebugMsg( "connected\r\n");
if( fnSendTCP(test_client_socket, data, 4, TCP_FLAG_PUSH) > 0) {
fnDebugMsg( "sent successfully\r\n");
} else {
fnDebugMsg( "send failed\r\n");
}
fnReleaseTCP_Socket( test_client_socket);
} else {
if( ret == SOCKET_NOT_FOUND)
fnDebugMsg( "Socket not found\r\n");
else if( ret == NO_FREE_PORTS_AVAILABLE)
fnDebugMsg( "No free ports available\r\n");
else if( ret == SOCKET_STATE_INVALID)
fnDebugMsg( "Socket state invalid\r\n");
}
} else {
if( test_client_socket == -2) {
fnDebugMsg( "No socket available\r\n");
}
}
}

I have the task set up to start after 10s and call fnMyFirstTask() every 10s.  This gives me enough time after starting the application to select the right NIC from the uTasker dialog.

I wrote a simple listener app in C# that listens on port 50000.  I know this app works because I have some code running on my FRDM-K64F that connects to the port and streams it data.  I can see the connection occur and bytes coming in.

When I run my application, via Telnet I can see that the socket gets created and connects successfully, and supposedly data is also sent successfully.  However, my app doesn't see the connection or byte stream.  On top of that, Wireshark reports some kind of error:

105964   4274.560943000   192.168.0.88   192.168.0.112   TCP   58   [TCP Out-Of-Order] 64416?50000 [SYN, PSH] Seq=0 Win=1460 Len=0

From reading the past posts in this thread, it sounds like it's possible that data could be sent, but not actually get received due to things like ACKs not being sent?  Anyhow, I put breakpoints in fnTestTcpServerConnect() and none of them get hit.  Actually, the function seems to not ever get called.

Can you provide me with any suggestions on debugging this further?  Can you also recommend any good reads for people that don't understand the nitty-gritty details of TCP, but want to learn?

Thank you!

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3234
    • View Profile
    • uTasker
Re: Using TCP in the uTasker project
« Reply #48 on: October 10, 2014, 12:49:43 PM »
Hi

>>This gives me enough time after starting the application to select the right NIC from the uTasker dialog

The selected NIC is stored when the simulator is closed normally. You should only ever have to set it once and then it should stay correct.

I think that the main problem that you have is that you are writing code as if the socket operation were blocking, but it is not blocking; you need to make use of the callback function so that the operation is state-event based.

Eg. After fnTCP_Connect(() returns with success it means that it has sent a SYN to the destination (or at least started ARP resolution so that this can be performed shortly) - it doesn't mean that there is a connection established, which is reported (after a short time - but could even be several seconds later if the distance involved is long and there needs to be a repetition due to lost data) by the event TCP_EVENT_CONNECTED at the callback.

Therefore you need to place the code that sends in the callback instead.

You will also get an event confirming that your data was successfully received and then you can close the connection.
Generally there is no advantage in releasing the socket if you want to use it again later. If you initialise it to -1 and only call fnGetTCP_Socket() when it is negatiev it will save calling it multiple times.

You can find examples towards the beginning of this thread and it is useful to put to some fnDebugMsg() in the callback so that you see the events taking place and then you will quickly get the idea of the operation. Note that you hae teh choice between simple sockets, buffered sockets and TELNET-like sockets. Start with the simple socket operation since it will show the complete workings and uses least resources. Then try buffered socket (allows greater transmit speed at the cost of buffer space) and finalyl a TELNET-like socket which is the simplest to use since it encapsulates TELNET code to handle most of the nitty-gritty.

TCP illustrated is the classic book (although a bit outdated now): https://www.goodreads.com/book/show/505560.The_Protocols


Regards

Mark
« Last Edit: October 10, 2014, 01:10:09 PM by mark »

Offline k64konfused

  • Newbie
  • *
  • Posts: 25
    • View Profile
Re: Using TCP in the uTasker project
« Reply #49 on: October 10, 2014, 02:53:47 PM »
Hi Mark, as usual, thank you for the comprehensive (and comprehensible!) explanation.  The reason I was doing that was a) misunderstanding, and b) I was trying to do it quick-and-dirty, so closing the connection each time from a periodic task was necessary.  I haven't yet looked into how to initialize peripherals / features.  Ideally, I would open a listening socket upon startup, and then have multiple remote sockets get created only once when a connection needs to be made to its respective server/device.  Then in the periodic task I would just send ModbusTCP commands over each connection, and only close the socket upon shutdown.

I will definitely proceed in the order that you have recommended.  Hopefully, I will become more well-versed in TCP details in the coming weeks.

Thank you!